我最近遇到了FileChannel,我是RandomAccessFile的忠实粉丝。但我想知道为什么我会选择
FileChannel
而不是 RandomAccessFile
来读取文件并将该内容写入另一个文件。
有什么具体的性能原因吗?我不想出于任何目的使用
FileChannel
的锁定,因为我认为这可能是可以使用文件通道的原因之一。我不想使用 BufferReader
或 other StackOverflow 响应中建议的任何类似内容。
FileChannel API 说:文件的一个区域可以直接映射到内存中;对于大文件,这通常比调用通常的读取或写入方法更有效。
除非您使用带有直接缓冲区的
FileChannel
并且从不自己访问数据,否则它们之间没有什么可供选择的,例如你只需将它复制到 SocketChannel.
这样更快,因为数据永远不必跨越 JNI/JVM 边界。
但我想知道你为什么不选择
BufferedReader
。对于逐行读取文件,它肯定比其中任何一个快几个数量级。
它们的区别在于内存和I/O deivde之间传输数据的机制。
RandomAccessFile
使用 Programmed I/O。
传输的数据经过 3 个阶段。例如:对于一个读操作,数据首先从I/O设备到CPU寄存器,然后从寄存器到内存。每次I/O数据准备好,就中断CPU让CPU去处理。当文件很大时,需要占用大量的 cpu 时间片。
FileChannel
使用 Direct Memory Access。直接在内存和 I/O 设备之间传输的数据。
一般来说,对于大文件,DMA会比PIO效率高很多
RandomAccessFile 性能良好,而且它允许直接读写大多数主要类型。
FileChannels 可以安全地供多个并发线程使用。
RandomAccess文件来源:
看到 RandomAccessFile 实际上在幕后使用 FileChannel ...
public final FileChannel getChannel() {
synchronized (this) {
if (channel == null) {
channel = FileChannelImpl.open(fd, true, rw, this);
/*
* FileDescriptor could be shared by FileInputStream or
* FileOutputStream.
* Ensure that FD is GC'ed only when all the streams/channels
* are done using it.
* Increment fd's use count. Invoking the channel's close()
* method will result in decrementing the use count set for
* the channel.
*/
fd.incrementAndGetUseCount();
}
return channel;
}
}