Java 中的内存映射文件

发布于 2024-07-25 12:33:13 字数 896 浏览 1 评论 0原文

我一直在尝试编写一些非常快速、需要执行大量 I/O 的 Java 代码。 我正在使用返回 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;
}

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

我应该把所有东西都包起来吗? 或者我应该把所有东西都写一遍?

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:

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.

Should I just wrap everything? Or should I double-write everything?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

琉璃繁缕 2024-08-01 12:33:13

是否有人真正检查过内存映射创建的 ByteBuffers 是否首先支持调用 .array() ,无论只读/读写?

根据我的探索,据我所知,答案是ByteBuffer 通过 ByteBuffer.array() 返回直接 byte[] 数组的能力取决于 ByteBuffer 的存在.hb (byte[]),在创建 MappedByteBuffer 时始终设置为 null。

这对我来说有点糟糕,因为我希望做一些类似于问题作者想做的事情。

Did anyone actually check to see if ByteBuffers created by memory mapping support invoking .array() in the first place, regardless of readonly/readwrite?

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.

Which kinda sucks for me, because I was hoping to do something similar to what the question author wanted to do.

我要还你自由 2024-08-01 12:33:13

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

这是它服务的场景。 假设您有一些数据
更喜欢保留在内存中,但你事先不知道有多少数据
那里将是。 如果太多,你想将其写入磁盘
而不是占用内存,但您不想写入磁盘,直到您
需要,因为磁盘速度很慢并且是需要跟踪的资源
清理。

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

这就是 DeferredOutputStream 为您所做的事情。 它隐藏了所有的混乱
在切换点附近。 您需要做的就是创建
首先延迟流,配置阈值,然后就可以了
随心所欲地写下来。

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

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

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 DeferredOutputStream does 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.

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.

柒夜笙歌凉 2024-08-01 12:33:13

包装 byte[] 不会减慢速度...不会有任何巨大的数组副本或其他小的性能问题。 来自JavaDocs: java.nio.ByteBuffer
.wrap()

将字节数组包装到缓冲区中。

新缓冲区将由给定的字节数组支持;也就是说,
对缓冲区的修改会导致
要修改的数组和副数组
反之亦然。 新缓冲区的容量和
limit 将是 array.length,其
位置将为零,其标记
将是未定义的。 它的支持阵列
将是给定的数组及其数组
偏移量将为零。

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()

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.

一梦浮鱼 2024-08-01 12:33:13

使用 ByteBuffer.wrap() 功能不会造成很大的负担。 它分配一个简单的对象并初始化一些整数。 因此,如果您需要处理只读文件,那么针对 ByteBuffer 编写算法是您的最佳选择。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文