Java 中的内存映射文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1023200/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Memory-mapped files in Java
提问by vy32
I've been trying to write some very fast Java code that has to do a lot of I/O. I'm using a memory mapped file that returns a ByteBuffer:
我一直在尝试编写一些非常快速的 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;
}
The problem that I'm having is that the ByteBuffer .array() method (which should return a byte[] array) doesn't work for read-only files. I want to write my code so that it will work with both memory buffers constructed in memory and buffers read from the disk. But I don't want to wrap all of my buffers a ByteBuffer.wrap() function because I'm worried that this will slow things down. So I've been writing two versions of everything, one that takes a byte[], the other that takes a ByteBuffer.
我遇到的问题是 ByteBuffer .array() 方法(它应该返回一个 byte[] 数组)不适用于只读文件。我想编写我的代码,以便它可以与在内存中构造的内存缓冲区和从磁盘读取的缓冲区一起使用。但我不想将我所有的缓冲区都包装成 ByteBuffer.wrap() 函数,因为我担心这会减慢速度。所以我一直在写所有东西的两个版本,一个需要一个 byte[],另一个需要一个 ByteBuffer。
Should I just wrap everything? Or should I double-write everything?
我应该把所有东西都包起来吗?还是我应该把所有东西都写一遍?
采纳答案by Trevor Harrison
Did anyone actually check to see if ByteBuffers
created by memory mapping support invoking .array()
in the first place, regardless of readonly/readwrite?
有没有人真正检查过是否ByteBuffers
由内存映射创建的支持.array()
首先调用,而不管只读/读写?
From my poking around, as far as I can tell, the answer is NO. A ByteBuffer
's ability to return a direct byte[]
array via ByteBuffer.array()
is goverened by the presence of ByteBuffer.hb
(byte[]
), which is always set to null when a MappedByteBuffer
is created.
据我所知,答案是否定的。A通过( )的存在ByteBuffer
返回直接byte[]
数组的能力,在创建a 时它始终设置为 null 。ByteBuffer.array()
ByteBuffer.hb
byte[]
MappedByteBuffer
Which kinda sucks for me, because I was hoping to do something similar to what the question author wanted to do.
这对我来说有点糟糕,因为我希望做一些类似于问题作者想要做的事情。
回答by Jherico
Using the ByteBuffer.wrap() functionality does not impose a high burden. It allocates a simple object and initializes a few integers. Writing your algorithm against ByteBuffer is thus your best bet if you need to work with read only files.
使用 ByteBuffer.wrap() 功能不会带来很高的负担。它分配一个简单的对象并初始化一些整数。因此,如果您需要处理只读文件,那么针对 ByteBuffer 编写算法是最好的选择。
回答by Stu Thompson
Wrapping byte[] won't slow things down...there won't be any huge array copies or other little performance evils. From the JavaDocs: java.nio.ByteBuffer .wrap()
包装 byte[] 不会减慢速度......不会有任何巨大的数组副本或其他小的性能问题。来自 JavaDocs:java.nio.ByteBuffer .wrap()
Wraps a byte array into a buffer.
The new buffer will be backed by the the given byte array;that is, modifications to the buffer will cause the array to be modified and vice versa. The new buffer's capacity and limit will be array.length, its position will be zero, and its mark will be undefined. Its backing array will be the given array, and its array offset will be zero.
将字节数组包装到缓冲区中。
新缓冲区将由给定的字节数组支持;也就是说,对缓冲区的修改将导致数组被修改,反之亦然。新缓冲区的容量和限制将为 array.length,其位置为零,其标记为未定义。它的后备数组将是给定的数组,它的数组偏移量将为零。
回答by Gaurav Saini
Its always good not to reinvent the wheels. Apache has provided a beautiful library for performing I/O operations. Take a look at http://commons.apache.org/io/description.html
不重新发明轮子总是好的。Apache 为执行 I/O 操作提供了一个漂亮的库。看看 http://commons.apache.org/io/description.html
Here's the scenario it serves. Suppose you have some data that you'd prefer to keep in memory, but you don't know ahead of time how much data there is going to be. If there's too much, you want to write it to disk instead of hogging memory, but you don't want to write to disk until you need to, because disk is slow and is a resource that needs tracking for cleanup.
这是它所服务的场景。假设您希望将一些数据保存在内存中,但您不知道将有多少数据。如果太多,您希望将其写入磁盘而不是占用内存,但您不想在需要之前写入磁盘,因为磁盘很慢并且是需要跟踪以进行清理的资源。
So you create a temporary buffer and start writing to that. If / when you reach the threshold for what you want to keep in memory, you'll need to create a file, write out what's in the buffer to that file, and write all subsequent data to the file instead of the buffer.
所以你创建一个临时缓冲区并开始写入。如果/当您达到要保留在内存中的内容的阈值时,您需要创建一个文件,将缓冲区中的内容写入该文件,并将所有后续数据写入文件而不是缓冲区。
That's what DeferredOutputStreamdoes for you. It hides all the messing around at the point of switch-over. All you need to do is create the deferred stream in the first place, configure the threshold, and then just write away to your heart's content.
这就是DeferredOutputStream为您所做的。它隐藏了切换点的所有混乱。您需要做的就是首先创建延迟流,配置阈值,然后写出您的心声。
EDIT: I just did a small re-search using google and found this link: http://lists.apple.com/archives/java-dev/2004/Apr/msg00086.html(Lightning fast file read/write). Very impressive.
编辑:我刚刚使用谷歌做了一个小的重新搜索,找到了这个链接:http: //lists.apple.com/archives/java-dev/2004/Apr/msg00086.html(Lightning 快速文件读/写)。非常令人印象深刻。