问题 扩展Java内存映射字节缓冲区


有没有办法扩展Java内存映射字节缓冲区,以便新的大小反映回磁盘上的映射文件?


11703
2018-06-12 11:40


起源



答案:


不,您需要调整底层文件的大小并重新创建Memory Mapped Byte Buffer。

RandomAccessFile file = new RandomAccessFile(/* some file */);
MappedByteBuffer buffer = file.getChannel().map(MapMode.READ_WRITE, 0, file.length());

// Some stuff happens...

// adjust the size
file.setLength(newLength);

// recreate the memory mapped buffer
buffer = file.getChannel().map(MapMode.READ_WRITE, 0, file.length());

注意:设置文件长度有一些奇怪的行为。如果您通过地图在超出文件末尾的特定位置(使用map.position()或map.putX(position,...))写入文件,则值将附加到文件末尾该文件并没有写在您期望的位置(至少在Linux上)。如果这是不期望的行为,则需要将数据附加到文件以便真正增长文件。


10
2018-06-12 12:09



请你解释奇怪的行为换句话说?如果我写的超出它的末尾(通过映射的缓冲区,假设它映射整个文件大小),是否不期望附加到文件的末尾? - geeko
从50字节大小的文件开始。调用setLength(1000)来增加文件的大小。然后从文件中创建一个新的映射(file.getChannel()。map(...,0,1000)。如果在新的MappedByteBuffer上调用putByte(500,(byte)'x'),则值'x'将显示为文件中的第50个字节(基于0的索引)而不是位置500(可能不是奇数,但可能是意外行为)。 - Michael Barker
我明白你的意思。谢谢迈克尔。 - geeko
我需要关闭缓冲区吗? - Karussell
嗯,似乎没有unmap bugs.sun.com/view_bug.do?bug_id=4724038 - Karussell


答案:


不,您需要调整底层文件的大小并重新创建Memory Mapped Byte Buffer。

RandomAccessFile file = new RandomAccessFile(/* some file */);
MappedByteBuffer buffer = file.getChannel().map(MapMode.READ_WRITE, 0, file.length());

// Some stuff happens...

// adjust the size
file.setLength(newLength);

// recreate the memory mapped buffer
buffer = file.getChannel().map(MapMode.READ_WRITE, 0, file.length());

注意:设置文件长度有一些奇怪的行为。如果您通过地图在超出文件末尾的特定位置(使用map.position()或map.putX(position,...))写入文件,则值将附加到文件末尾该文件并没有写在您期望的位置(至少在Linux上)。如果这是不期望的行为,则需要将数据附加到文件以便真正增长文件。


10
2018-06-12 12:09



请你解释奇怪的行为换句话说?如果我写的超出它的末尾(通过映射的缓冲区,假设它映射整个文件大小),是否不期望附加到文件的末尾? - geeko
从50字节大小的文件开始。调用setLength(1000)来增加文件的大小。然后从文件中创建一个新的映射(file.getChannel()。map(...,0,1000)。如果在新的MappedByteBuffer上调用putByte(500,(byte)'x'),则值'x'将显示为文件中的第50个字节(基于0的索引)而不是位置500(可能不是奇数,但可能是意外行为)。 - Michael Barker
我明白你的意思。谢谢迈克尔。 - geeko
我需要关闭缓冲区吗? - Karussell
嗯,似乎没有unmap bugs.sun.com/view_bug.do?bug_id=4724038 - Karussell