2012-02-03 87 views
2

我知道如何创建一个内存映射文件,但我的问题是,我们说的是,在下面一行:内存映射文件的Java NIO

FileChannel roChannel = new RandomAccessFile(file, "r").getChannel(); 
ByteBuffer roBuf = roChannel.map(FileChannel.MapMode.READ_ONLY, 0, SIZE); 

如果我设置大小为例如2MB,做到这一点的手段它只会加载2MB的文件,还是会在文件中进一步读取,并更新缓冲区,因为我从中消耗了字节?

+5

只有映射的部分可以通过该缓冲区访问。把它想象成整个文件的一个窗口,只有可见区域可以被读取(写入) – bestsss 2012-02-03 01:33:13

+0

@bestsss:你应该把它作为一个答案来代替。 – Jonas 2012-02-03 01:39:34

+0

@Jonas,...不喜欢单个句子中的答案。答案也很明显。提问者总是可以自己回复并选择它。 – bestsss 2012-02-03 01:56:56

回答

2

缓冲区的大小是您传入的大小,它不会增长或缩小。

javadoc说:

地图上的这个通道的文件区域直接到内存中。

...

尺寸 - 该区域的大小要被映射;必须为非负且不大于Integer.MAX_VALUE的

编辑更大:

根据你所说的什么“更新了新的数据”,答案是肯定的。

通过这个类的一个实例提供的文件的视图保证与由在同一程序中其他实例提供同一文件的其它视图相一致。然而,由这个类的一个实例提供的视图可能会或可能不会与由其他并发运行的程序看到的视图一致,这是由于底层操作系统执行的缓存和网络文件系统协议引起的延迟。无论编写这些其他程序的语言如何,以及它们是在同一台机器上还是在其他某台机器上运行,情况都是如此。任何此类不一致的确切性质都与系统有关,因此未予指明。

,因此,其他系统可能会做缓存,但是当这些高速缓存清空或以其他方式跟上时代的,他们将与由FileChannel提出的观点。

您还可以使用显式调用position方法和其他方法来更改视图呈现的内容。

更改通道的位置,无论是显式读取还是通过读取或写入字节,都会更改原始对象的文件位置,反之亦然。通过文件通道更改文件的长度将改变通过原始对象看到的长度,反之亦然。通过写入字节来更改文件的内容将改变原始对象看到的内容,反之亦然。

+0

我知道缓冲区不会增长,我的问题是当我消耗的时候它是否会随新数据更新,javadoc在这方面并不十分清楚。 – raygozag 2012-02-04 04:57:34

+0

@raygozag,请参阅我的编辑。 – 2012-02-04 13:59:24

4

其中i集合大小是例如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一个是,它不一定会实际上整个缓冲区加载到内存中,而是只有你访问的部分。