Java内存映射大文件

4

Java中MappedByteBuffer的2GIG限制使得它在映射大文件时变得棘手。通常推荐的方法是使用MappedByteBuffer数组,并通过索引进行访问:

long PAGE_SIZE = Integer.MAX_VALUE;
MappedByteBuffer[] buffers;

private int getPage(long offset) {
    return (int) (offset / PAGE_SIZE)
}

private int getIndex(long offset) {
    return (int) (offset % PAGE_SIZE);
}

public byte get(long offset) {
    return buffers[getPage(offset)].get(getIndex(offset));
}

这可以适用于单个字节的工作,但如果您想处理更大并且需要跨越边界(getLong()或get(byte[]))的读/写,则需要重写大量代码。

问题是:在这些情况下,您的最佳实践是什么?您是否知道任何可重复使用的工作解决方案/代码,而无需重新发明轮子?


Integer.MAX_VALUE 不是2的幂,也不是底层页面大小(通常为4KB)的倍数。不幸的是。 - Peter Lawrey
抱歉,我没有理解你的评论。 - marcorossi
在内部,它通过页面大小对DirectByteBuffers进行了对齐,我认为,使用未按页面对齐的数据会更低效,并且我假设不允许。(但是我已经测试过了,它是可以的) - Peter Lawrey
你可以直接使用底层本地方法(通过反射)映射大于2GB的块,但我还没有找到如何强制将其写入磁盘。我怀疑这并不算是最佳实践,但速度可能会快得多。 ;) - Peter Lawrey
你有没有阅读上次你提出类似问题时的答案/评论:https://dev59.com/lG035IYBdhLWcg3wHsOR - Anon
是的,正如您所看到的,每个都有我的评论。实际上,昨天还有一个。 - marcorossi
1个回答

6
你看过 dsiutil 的 ByteBufferInputStream 吗?

Javadoc

这个类的主要用途是创建真正基于 MappedByteBuffer 的输入流。

特别地,工厂方法 map(FileChannel, FileChannel.MapMode) 将整个文件映射到一个 ByteBuffer 数组中,并将该数组作为 ByteBufferInputStream 显露出来。这使得可以轻松访问大于 2GiB 的映射文件。

  • long length()
  • long position()
  • void position(long newPosition)

这是你想了解的内容吗?它也是LGPL授权的


太棒了!在这里查看:http://mvnrepository.com/artifact/it.unimi.dsi/dsiutils Sebastiano Vigna 真是太棒了! - aaiezza

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接