最有效合并2个文本文件。

时间:2011-10-04 15:24:42

标签: java performance algorithm java-io

所以我有成对的大文件(大约4演出)txt文件,我需要创建一个第3个文件,其中包含shuffle模式下的2个文件。以下等式表示最佳:

3rdfile =(文件1中的4行)+(文件2中的4行)并重复此操作直到我到达文件1的末尾(两个输入文件将具有相同的长度 - 这是根据定义)。这是我现在使用的代码,但这在大文件上的扩展性不是很好。我想知道是否有更有效的方法来执行此操作 - 是否可以使用内存映射文件帮助?欢迎所有的想法。

public static void mergeFastq(String forwardFile, String reverseFile, String outputFile) {

    try {
        BufferedReader inputReaderForward = new BufferedReader(new FileReader(forwardFile));
        BufferedReader inputReaderReverse = new BufferedReader(new FileReader(reverseFile));
        PrintWriter outputWriter = new PrintWriter(new FileWriter(outputFile, true));

        String forwardLine = null;
        System.out.println("Begin merging Fastq files");
        int readsMerge = 0;
        while ((forwardLine = inputReaderForward.readLine()) != null) {

            //append the forward file
            outputWriter.println(forwardLine);
            outputWriter.println(inputReaderForward.readLine());
            outputWriter.println(inputReaderForward.readLine());
            outputWriter.println(inputReaderForward.readLine());
            //append the reverse file
            outputWriter.println(inputReaderReverse.readLine());
            outputWriter.println(inputReaderReverse.readLine());
            outputWriter.println(inputReaderReverse.readLine());
            outputWriter.println(inputReaderReverse.readLine());

            readsMerge++;
            if(readsMerge % 10000 == 0) {
                System.out.println("[" + now() + "] Merged 10000");
                readsMerge = 0;
            }

        }

        inputReaderForward.close();
        inputReaderReverse.close();
        outputWriter.close();

    } catch (IOException ex) {
        Logger.getLogger(Utilities.class.getName()).log(Level.SEVERE, "Error while merging FastQ files", ex);
    }
}

4 个答案:

答案 0 :(得分:2)

也许您还想尝试使用BufferedWriter来减少文件IO操作。 http://download.oracle.com/javase/6/docs/api/java/io/BufferedWriter.html

答案 1 :(得分:0)

一个简单的答案是使用更大的缓冲区,这有助于减少正在进行的I / O调用总数。

通常,使用FileChannel(请参阅Java NIO)的内存映射IO将用于处理大型数据文件IO。但是,在这种情况下,情况并非如此,因为您需要检查文件内容以确定每4行的边界。

答案 2 :(得分:0)

缓冲您的读写操作。缓冲区需要足够大,以最大限度地减少读/写操作,并保持内存效率。这很简单,很有效。

void write(InputStream is, OutputStream os) throws IOException {
    byte[] buf = new byte[102400]; //optimize the size of buffer to your needs
    int num;
    while((n = is.read(buf)) != -1){
        os.write(buffer, 0, num);
    }
}

编辑: 我刚刚意识到你需要对这些行进行洗牌,所以这段代码不适合你,但概念仍然保持不变。

答案 3 :(得分:0)

如果性能是主要要求,那么我将用C或C ++代替Java来编写这个函数。

但无论使用何种语言,我要做的就是尝试自己管理记忆。我会创建两个大缓冲区,比如1​​28MB或更多,并用两个文本文件中的数据填充它们。然后你需要一个比前两个大两倍的第三个缓冲区。该算法将开始从输入缓冲区#1逐个移动字符到目标缓冲区,同时计算EOL。到达第4行后,将当前位置存储在该缓冲区上,并使用第2个输入缓冲区重复相同的过程。您继续在两个输入缓冲区之间交替,在消耗缓冲区中的所有数据时补充缓冲区。每次必须重新填充输入缓冲区时,您还可以编写目标缓冲区并清空它。