3

Javaでテキストファイルを連結するために思いついた2つの方法のうち、どちらが優れているかを知りたいと思います。FileChannelへのこれらの書き込み方法の違いを説明するカーネルレベルで何が起こっているかについて誰かが共有できる洞察を持っているなら、私はそれを大いに感謝します。

ドキュメントやその他のStackOverflowの会話から私が理解していることから、allocateDirectはドライブにスペースを割り当て、ほとんどの場合RAMの使用を回避します。ファイルのファイルが大きい場合、たとえば1GBの場合、allocateDirectで作成されたByteBufferがオーバーフローしたり、割り当てられなかったりする可能性があるのではないかと心配しています。ソフトウェア開発のこの時点で、ファイルは2GB以下であることが保証されています。ただし、将来的には10GBまたは20GBになる可能性があります。

transferFromループがループを2回以上通過することはないことを確認しました...したがって、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 に答える