Java中的内存映射文件

vy3*_*y32 8 java memory-mapping

我一直在尝试编写一些非常快速的Java代码,它必须执行大量的I/O. 我正在使用返回ByteBuffer的内存映射文件:

public static ByteBuffer byteBufferForFile(String fname){
    FileChannel vectorChannel;
    ByteBuffer vector;
    try {
        vectorChannel = new FileInputStream(fname).getChannel();
    } catch (FileNotFoundException e1) {
        e1.printStackTrace();
        return null;
    }
    try {
        vector = vectorChannel.map(MapMode.READ_ONLY,0,vectorChannel.size());
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }
    return vector;
}
Run Code Online (Sandbox Code Playgroud)

我遇到的问题是ByteBuffer .array()方法(应返回byte []数组)不适用于只读文件.我想编写我的代码,以便它可以与内存中构造的内存缓冲区和从磁盘读取的缓冲区一起使用.但是我不想把我的所有缓冲区都包装成ByteBuffer.wrap()函数,因为我担心这会减慢速度.所以我一直在编写所有内容的两个版本,一个采用byte [],另一个采用ByteBuffer.

我应该把一切都包好吗?或者我应该双重写一切?

Tre*_*son 10

有没有人实际检查是否ByteBuffers由内存映射支持.array()首先调用创建,而不管readonly/readwrite?

从我的角度来看,据我所知,答案是否定的.甲ByteBuffer的能力返回一个直接byte[]经由阵列ByteBuffer.array()是由存在goverened ByteBuffer.hb(byte[])中,当其被一直设置为空MappedByteBuffer被创建.

哪种方式对我来说很糟糕,因为我希望做一些与作者想要做的事情类似的事情.

  • `byte []`必须在堆上.内存映射的内存块必须位于堆外.如果区别是透明的,那将是很好的,但我更喜欢使用ByteBuffer的getLong/putLong方法(这些使用本机排序要快得多) (3认同)

Gau*_*ini 5

总是不要重新发明轮子.Apache提供了一个用于执行I/O操作的漂亮库.看看 http://commons.apache.org/io/description.html

这是它所服务的场景.假设您有一些您希望保留在内存中的数据,但您事先并不知道将会有多少数据.如果有太多,你想将它写入磁盘而不是占用内存,但是你不想在需要之前写入磁盘,因为磁盘很慢并且是需要跟踪清理的资源.

所以你创建一个临时缓冲区并开始写入.如果/当您达到要保留在内存中的阈值时,则需要创建一个文件,将缓冲区中的内容写出到该文件,然后将所有后续数据写入文件而不是缓冲区.

这就是DeferredOutputStream为您所做的.它隐藏了切换时所有的麻烦.您需要做的就是首先创建延迟流,配置阈值,然后只记录您心中的内容.

编辑:我只是使用谷歌做了一个小的重新搜索,发现此链接:http: //lists.apple.com/archives/java-dev/2004/Apr/msg00086.html (闪电快速文件读/写).非常令人印象深刻.