内存映射文件java NIO
Posted
技术标签:
【中文标题】内存映射文件java NIO【英文标题】:Memory mapped file java NIO 【发布时间】:2012-02-03 01:30:43 【问题描述】:我了解如何创建内存映射文件,但我的问题是让我们在以下行中说:
FileChannel roChannel = new RandomAccessFile(file, "r").getChannel();
ByteBuffer roBuf = roChannel.map(FileChannel.MapMode.READ_ONLY, 0, SIZE);
例如,我将 SIZE 设置为 2MB,这是否意味着它只会加载 2MB 的文件,还是会在文件中进一步读取并在我消耗字节时更新缓冲区?
【问题讨论】:
只有映射的部分可以通过该缓冲区访问。把它想象成一个覆盖整个文件的窗口,只能读取(写入)可见区域 @bestsss:您应该将其添加为答案。 @Jonas, ...不喜欢一句话的答案。答案也很明显。提问者可以随时自行回复并选择它。 【参考方案1】:例如,我将 SIZE 设置为 2MB,这是否意味着它只会加载 2MB 的文件,还是会在文件中进一步读取并在我消耗字节时更新缓冲区?
它只会加载在缓冲区初始化中指定的文件部分。如果你想让它进一步阅读,你需要有某种阅读循环。虽然我不会说这很棘手,但如果一个人不是 100% 熟悉所涉及的 java.io 和 java.nio API,那么把它塞满的可能性就很高。 (例如:不翻转缓冲区;缓冲区/文件边缘情况错误)。
如果您正在寻找一种在 ByteBuffer 中访问此文件的简单方法,请考虑使用 MappedByteBuffer
。
RandomAccessFile raf = new RandomAccessFile(file, "r");
FileChannel fc = raf.getChannel();
MappedByteBuffer buffer = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
在这种情况下使用 MBB 的好处是它不一定会实际将整个缓冲区加载到内存中,而只会加载您正在访问的部分。
【讨论】:
【参考方案2】:缓冲区的大小是你传入的大小。它不会增长或缩小。
javadoc 说:
将此通道文件的一个区域直接映射到内存中。
...
size - 要映射的区域的大小;必须为非负且不大于 Integer.MAX_VALUE
编辑:
根据您所说的“使用新数据更新”的含义,答案是肯定的。
该类的实例提供的文件视图保证与同一程序中其他实例提供的同一文件的其他视图一致。但是,由于底层操作系统执行的缓存和网络文件系统协议引起的延迟,此类实例提供的视图可能与其他并发运行的程序看到的视图一致,也可能不一致。无论这些其他程序是用什么语言编写的,也不管它们是在同一台机器上还是在其他机器上运行,这都是正确的。任何此类不一致的确切性质取决于系统,因此未指定。
因此,其他系统可能会进行缓存,但是当这些缓存被刷新或以其他方式更新时,它们将同意FileChannel
呈现的视图。
您还可以使用对position
方法和其他方法的显式调用来更改视图呈现的内容。
改变通道的位置,无论是显式地还是通过读取或写入字节,都会改变原始对象的文件位置,反之亦然。通过文件通道更改文件的长度将更改通过原始对象看到的长度,反之亦然。通过写入字节更改文件的内容将更改原始对象看到的内容,反之亦然。
【讨论】:
我知道缓冲区不会增长,我的问题是它是否会在我消费时用新数据进行更新,javadoc 在这方面并不是很清楚。以上是关于内存映射文件java NIO的主要内容,如果未能解决你的问题,请参考以下文章
java大文件读写操作,java nio 之MappedByteBuffer,高效文件/内存映射
JavaNIO的深入研究4内存映射文件I/O,大文件读写操作,Java nio之MappedByteBuffer,高效文件/内存映射
作者推荐 | Java难点攻克「NIO和内存映射性能提升系列」彻底透析NIO底层的内存映射机制原理与Direct Memory的关系