3

我想使用ByteBuffer. 最后我想出了三个解决方案:

FileChannel inChannel = new FileInputStream("input.txt").getChannel();
FileChannel outChannel = new FileOutputStream("output.txt").getChannel();
ByteBuffer buf = ByteBuffer.allocate(1024 * 1024);

方法一:使用hasRemaining()

while (inChannel.read(buf) != -1) {
    buf.flip();    
    while (buf.hasRemaining()) {
        outChannel.write(buf);
    }    
    buf.clear();
}

方法二:使用compact()

while (inChannel.read(buf) != -1 || buf.position() > 0) {
    buf.flip();
    outChannel.write(buf);
    buf.compact();
}

方法三:混合模型

while (inChannel.read(buf) != -1) {
    buf.flip();
    outChannel.write(buf);
    buf.compact();
}
// final flush of pending output
while (buf.hasRemaining())
    outChannel.write(buf);

问题是:哪种方法的性能和吞吐量最高?

4

2 回答 2

3

你为什么要使用compact()呢?- 它可能涉及重复复制大量数据。

如果您没有充分的理由在写入所有先前读取的数据之前执行另一次读取,则您的第一种方法是可行的方法。

哦,顺便说一句:如果您只是想将数据从一个文件复制到另一个文件,请查看transferTo(), 或transferFrom(). 这是文件复制的最高性能方式,因为这可能会使用底层操作系统的非常有效的操作,例如 DMA。

(编辑: transferTo() 等当然不需要任何 ByteBuffer,混合了两种想法:))

于 2011-10-30T11:22:18.820 回答
1

为了最大限度地提高性能,我建议您尝试使用大约 32 KB 的直接缓冲区。根据您的系统,这种 16 KB 到 64 KB 的大小通常效果最佳。

对于文件通道,它应该能够每次都读取/写入所有数据,所以我认为各种方法不会有任何区别。但是,在读取/写入 Socket Channels 时会有所不同。

于 2011-10-30T12:15:35.943 回答