3

我想找出我想出的在 Java 中连接我的文本文件的两种方法中哪种方法更好。如果有人有一些见解,他们可以分享内核级别发生的事情,解释这些写入 FileChannel 的方法之间的区别,我将不胜感激。

根据我从文档和其他 Stack Overflow 对话中了解到的情况,allocateDirect 在驱动器上分配空间,并且主要避免使用 RAM。我担心如果 File infile 很大,比如 1GB,使用 allocateDirect 创建的 ByteBuffer 可能会溢出或不被分配。在开发我们的软件时,我保证文件不会大于 2 GB;但未来有可能达到 10 或 20GB。

我观察到 transferFrom 循环永远不会多次通过循环......所以它似乎一次成功地写入了整个 infile;但我没有用大于 60MB 的文件对其进行测试。我还是循环了,因为文档指定不能保证一次写多少。在我的系统上,由于 transferFrom 只能接受 int32 作为其计数参数,我将无法一次指定超过 2GB 的传输...再次,内核专业知识将帮助我理解。

在此先感谢您的帮助!!

使用 ByteBuffer

boolean concatFiles(StringBuffer sb, File infile, File outfile) {

    FileChannel inChan = null, outChan = null;

    try {

        ByteBuffer buff = ByteBuffer.allocateDirect((int)(infile.length() + sb.length()));
        //write the stringBuffer so it goes in the output file first:
        buff.put(sb.toString().getBytes());

        //create the FileChannels:
        inChan  = new RandomAccessFile(infile,  "r" ).getChannel();
        outChan = new RandomAccessFile(outfile, "rw").getChannel();

        //read the infile in to the buffer:
        inChan.read(buff);

        // prep the buffer:
        buff.flip();

        // write the buffer out to the file via the FileChannel:
        outChan.write(buff);
        inChan.close();
        outChan.close();
     } catch...etc

}

使用 trasferTo(或 transferFrom)

boolean concatFiles(StringBuffer sb, File infile, File outfile) {

    FileChannel inChan = null, outChan = null;

    try {

        //write the stringBuffer so it goes in the output file first:    
        PrintWriter  fw = new PrintWriter(outfile);
        fw.write(sb.toString());
        fw.flush();
        fw.close();

        // create the channels appropriate for appending:
        outChan = new FileOutputStream(outfile, true).getChannel();
        inChan  = new RandomAccessFile(infile, "r").getChannel();

        long startSize = outfile.length();
        long inFileSize = infile.length();
        long bytesWritten = 0;

        //set the position where we should start appending the data:
        outChan.position(startSize);
        Byte startByte = outChan.position();

        while(bytesWritten < length){ 
            bytesWritten += outChan.transferFrom(inChan, startByte, (int) inFileSize);
            startByte = bytesWritten + 1;
        }

        inChan.close();
        outChan.close();
    } catch ... etc
4

1 回答 1

3

transferTo() 可以更有效,因为数据复制更少,或者如果可以在内核中完成,则没有。如果它不在您的平台上,它仍将使用高度优化的代码。

你确实需要循环,有一天它会迭代,你的代码会继续工作。

于 2011-05-20T01:04:44.427 回答