解决方案 »

  1.   

    写的时候判断。可以参考log4j的实现
      

  2.   

    先遍历该文件夹下的所有txt文档,将其内容写入一个临时的大的txt文档,
    然后继续遍历创建文本文档,(每读取1mb的内容就创建一个txt,写入1mb)
      

  3.   

    抽时间给楼主写了一个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();
    }
    }
    }
      

  4.   

    大致的思路,谁都会说,就是具体的细节方面需要理清楚。
    1. 文本文件的字符处理,需要知道,文件的数据是存在字符编码的。
        例如:GBK编码中,汉字是2字节、英文数字是1字节。
    2. 分割文件的时候,由于数据存在编码,就不能按字节大小精确分割。
        因为,有可能将一个汉字的数据拆分到两个文件中,使得两个文件的末尾和开头出现乱码(半个汉字数据)。
    3. 既然不能精确分割,那么数据处理的时候,尽量面向字符编程而不是面向二进制流来编程。
        但是,如果单纯面向字符编程时,又无法准确判断写入文件的二进制数据的大小。(汉字和英文混排的文本)
    4. 将文件的合并与分割分成两个部分进行编码开发。
        一个部分的功能是将所有要求的文件数据写入到同一个Writer(面向字符编程)里。这个部分需要遍历文件夹,筛选出文本文件。递归遍历时,为防止递归死循环(其实该案例理论上是不会出现的),添加了递归深度参数,如果不限制递归深度,将该参数去掉即可。
       另一个部分的功能是将输出的字符数据切换成多个文件进行存储。由于切换文件的规则是按照写入文件数据的最大值来进行切换的,那么,需要保存当前文件已经写入的数据量,这个数据量是二进制数据量,所以,构建了CounterOutputStream 这个类。利用OutputStreamWriter进行字符向二进制的转码,每写入一个字符都要进行一次转码(调用flush)。由于频繁flush输出的IO,从而引起写入数据的性能瓶颈,所以,创建了BufferedOutputStream,用了提升写入性能。
    5. 所有的技术环节都弄清楚了,剩下的就是将这些功能代码进行归类、封装、组合、调用了。
      

  5.   

    我自己是用楼上临时文件的方法实现的,但是调用delete方法删不掉那个临时文件,还有其他的一些问题没解决,
    期待大神的demo供本人参考哈