关于IO的一个程序问题,不知道该怎么做

aCoder2013 2014-04-24 10:48:28
编写一个程序,讲一个目录及其子目录下的所有的txt类型的文本文件内容
合并到若干个新的文本文件中,当第一个新产生的文件中存储的内容达到1M
bytes时,剩下的内容存储到第二个新的文件中,依次往下,
新产生的文本文件知名字依次为1.txt、2.txt。。。。

不知道这个问题该怎么处理,大概的思路有,但是不知道具体该怎么实现,
...全文
983 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
aCoder2013 2014-05-11
  • 打赏
  • 举报
回复
引用 7 楼 yankaiwuzhengbo 的回复:
抽个空帮你写个demo昂。。。
我自己是用楼上临时文件的方法实现的,但是调用delete方法删不掉那个临时文件,还有其他的一些问题没解决, 期待大神的demo供本人参考哈
yuhouqingchen_2648 2014-05-11
  • 打赏
  • 举报
回复
抽个空帮你写个demo昂。。。
teemai 2014-04-24
  • 打赏
  • 举报
回复
写的时候判断。 可以参考log4j的实现
tony4geek 2014-04-24
  • 打赏
  • 举报
回复
现在很多框架写日志都是这样的。 达到容量写到下一个。
aCoder2013 2014-04-24
  • 打赏
  • 举报
回复
引用 5 楼 preferme 的回复:
大致的思路,谁都会说,就是具体的细节方面需要理清楚。 1. 文本文件的字符处理,需要知道,文件的数据是存在字符编码的。 例如:GBK编码中,汉字是2字节、英文数字是1字节。 2. 分割文件的时候,由于数据存在编码,就不能按字节大小精确分割。 因为,有可能将一个汉字的数据拆分到两个文件中,使得两个文件的末尾和开头出现乱码(半个汉字数据)。 3. 既然不能精确分割,那么数据处理的时候,尽量面向字符编程而不是面向二进制流来编程。 但是,如果单纯面向字符编程时,又无法准确判断写入文件的二进制数据的大小。(汉字和英文混排的文本) 4. 将文件的合并与分割分成两个部分进行编码开发。 一个部分的功能是将所有要求的文件数据写入到同一个Writer(面向字符编程)里。这个部分需要遍历文件夹,筛选出文本文件。递归遍历时,为防止递归死循环(其实该案例理论上是不会出现的),添加了递归深度参数,如果不限制递归深度,将该参数去掉即可。 另一个部分的功能是将输出的字符数据切换成多个文件进行存储。由于切换文件的规则是按照写入文件数据的最大值来进行切换的,那么,需要保存当前文件已经写入的数据量,这个数据量是二进制数据量,所以,构建了CounterOutputStream 这个类。利用OutputStreamWriter进行字符向二进制的转码,每写入一个字符都要进行一次转码(调用flush)。由于频繁flush输出的IO,从而引起写入数据的性能瓶颈,所以,创建了BufferedOutputStream,用了提升写入性能。 5. 所有的技术环节都弄清楚了,剩下的就是将这些功能代码进行归类、封装、组合、调用了。
感谢大神的耐心指教,今天自己写了很久,老是有一些细节出错或者异常,很是烦躁,我会好好研究的!
冰思雨 2014-04-24
  • 打赏
  • 举报
回复
大致的思路,谁都会说,就是具体的细节方面需要理清楚。 1. 文本文件的字符处理,需要知道,文件的数据是存在字符编码的。 例如:GBK编码中,汉字是2字节、英文数字是1字节。 2. 分割文件的时候,由于数据存在编码,就不能按字节大小精确分割。 因为,有可能将一个汉字的数据拆分到两个文件中,使得两个文件的末尾和开头出现乱码(半个汉字数据)。 3. 既然不能精确分割,那么数据处理的时候,尽量面向字符编程而不是面向二进制流来编程。 但是,如果单纯面向字符编程时,又无法准确判断写入文件的二进制数据的大小。(汉字和英文混排的文本) 4. 将文件的合并与分割分成两个部分进行编码开发。 一个部分的功能是将所有要求的文件数据写入到同一个Writer(面向字符编程)里。这个部分需要遍历文件夹,筛选出文本文件。递归遍历时,为防止递归死循环(其实该案例理论上是不会出现的),添加了递归深度参数,如果不限制递归深度,将该参数去掉即可。 另一个部分的功能是将输出的字符数据切换成多个文件进行存储。由于切换文件的规则是按照写入文件数据的最大值来进行切换的,那么,需要保存当前文件已经写入的数据量,这个数据量是二进制数据量,所以,构建了CounterOutputStream 这个类。利用OutputStreamWriter进行字符向二进制的转码,每写入一个字符都要进行一次转码(调用flush)。由于频繁flush输出的IO,从而引起写入数据的性能瓶颈,所以,创建了BufferedOutputStream,用了提升写入性能。 5. 所有的技术环节都弄清楚了,剩下的就是将这些功能代码进行归类、封装、组合、调用了。
冰思雨 2014-04-24
  • 打赏
  • 举报
回复
抽时间给楼主写了一个demo,给楼主一个编程思路。
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 自定义功能的Writer , 可以随着写入文件的大小切换新文件进行输出。
 */
public class ShiftWriter extends Writer{

	public static final long DEFAUT_MAX_SIZE = 1*1024*1024;
	public static final String DEFAULT_CHARSET = "GBK";
	
	/** 可计数的输出流 */
	static class CounterOutputStream extends OutputStream{
		private OutputStream output;
		private long count=0;
		public CounterOutputStream(OutputStream output) {
			this.output = output;
		}

		@Override
		public void write(int b) throws IOException {
			output.write(b);
			count++;
		}
		
		public long getCount() {
			return count;
		}
	}
	
	
	private long maxSize;
	private File targetDir;
	private int fileIndex = 1;
	private String charset;
	
	public ShiftWriter(File targetDir) throws FileNotFoundException, UnsupportedEncodingException {
		this(targetDir,DEFAUT_MAX_SIZE,DEFAULT_CHARSET);
	}
	
	public ShiftWriter(File targetDir, String charset) throws FileNotFoundException, UnsupportedEncodingException {
		this(targetDir,DEFAUT_MAX_SIZE,charset);
	}
	
	/**
	 * 构造器函数,向指定的文件夹中写入文件,文件的数据量存在最大值,达到最大值后切换文件进行写入。
	 * @param targetDir 目标文件夹(目录)
	 * @param maxSize 文件的数据最大值
	 * @param charset 文件采用的字符编码
	 */
	public ShiftWriter(File targetDir, long maxSize, String charset) throws FileNotFoundException, UnsupportedEncodingException {
		if(maxSize<=0)throw new IllegalArgumentException("maxSize is wrong.");
		if(targetDir==null || !targetDir.exists() || !targetDir.isDirectory()){
			throw new IllegalArgumentException("target dir isn't exists.");
		}
		this.maxSize = maxSize;
		this.charset = charset;
		this.targetDir = targetDir;
		File targets[] = targetDir.listFiles();
		Pattern pattern = Pattern.compile("(\\d+)\\.(txt)");
		for(File file : targets){
			Matcher matcher = pattern.matcher(file.getName());
			if(matcher.matches()){
				int index = Integer.parseInt(matcher.group(1));
				fileIndex = index>fileIndex?index:fileIndex;
			}
		}
		shiftTarget();
	}
	
	private File targetFile;
	private BufferedOutputStream buffer;
	private CounterOutputStream counter;
	private OutputStreamWriter writer;
	
	private void shiftTarget() throws FileNotFoundException, UnsupportedEncodingException {
		do{
			targetFile = new File(targetDir,fileIndex+".txt");
			if(targetFile.exists() && targetFile.isFile()){
				if(targetFile.length()>=maxSize){
					fileIndex++;
					continue;
				}
			}
			break;
		}while(true);
		OutputStream output = new FileOutputStream(targetFile,true);
		buffer = new BufferedOutputStream(output);
		counter = new CounterOutputStream(buffer);
		writer = new OutputStreamWriter(counter, charset);
	}

	@Override
	public void write(char[] cbuf, int off, int len) throws IOException {
		writer.write(cbuf, off, len);
		writer.flush();
		if(counter.count>=maxSize){
			writer.close();
			buffer.flush();
			buffer.close();
			fileIndex++;
			shiftTarget();
		}
	}

	@Override
	public void flush() throws IOException {
		writer.flush();
		buffer.flush();
	}

	@Override
	public void close() throws IOException {
		writer.close();
		buffer.close();
	}
	
	/** 写入文件。将当前文件的数据写入到Writer中。 */
	private static void writeFile(File src, Writer writer) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(src), "GBK"));
		int ch = -1;
		try{
			while((ch=br.read())!=-1){
				writer.write(ch);
			}
		}finally{
			br.close();
		}
	}
	
	/** 
	 * 递归遍历源文件夹,将txt文件的数据写入到Writer中。
	 * @param dir 源文件夹
	 * @param level 递归深度。遍历几层文件夹。当前文件夹的值为1.
	 * @param writer 目标写入器(Writer)
	 */
	private static void mergeFiles(File dir, int level, Writer writer) throws IOException{
		if(level<0)return;
		if(dir.isDirectory()){
			for(File file : dir.listFiles()){
				mergeFiles(file, level-1, writer);
			}
		}
		if(dir.isFile() && dir.getName().toLowerCase().endsWith(".txt")){
			System.out.println(dir);
			writeFile(dir, writer);
		}
	}
	
	/**
	 * 测试用例
	 */
	public static void main(String[] args) throws IOException {
		File srcDir = new File("d:\\tmp\\examples");
		File targetDir = new File("d:\\tmp\\shift");
		Writer writer = new ShiftWriter(targetDir);
		try{
			mergeFiles(srcDir, 2, writer);
		}finally{
			writer.close();
		}
	}
}
oFengKun 2014-04-24
  • 打赏
  • 举报
回复
先遍历该文件夹下的所有txt文档,将其内容写入一个临时的大的txt文档, 然后继续遍历创建文本文档,(每读取1mb的内容就创建一个txt,写入1mb)

62,621

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧