Java NIO - MappedByteBuffer 的截断

Posted

技术标签:

【中文标题】Java NIO - MappedByteBuffer 的截断【英文标题】:Java NIO - truncation of MappedByteBuffer 【发布时间】:2014-03-04 11:29:56 【问题描述】:

我正在尝试使用MappedMemoryBuffer 从文件中存储/删除部分字节。 Atm,我使用以下方法:我在缓冲区中有一个位置标记文件中数据的结尾(缓冲区比文件大一点以适应追加)。每个数据块的长度是固定的,比如说 200 字节。

我首先关心的是文件末尾的“标记”。我可以看到两种方法:

    使用某种标记来表示实际数据的结尾,而文件大小可以更大(由于我出于附加原因将其保持稍大)。想出某种独特的字节序列可能会很棘手。 始终确保我们读入的文件是“完整的”,即如果该文件是 2000 字节,这意味着其中有 10 条消息,仅此而已。我认为这更加棘手,因为我们必须不断截断文件大小并且使用非常麻烦的开放内存缓冲区(无法使用开放内存映射文件截断文件大小)

这就是为什么我会更倾向于一个,除非有人知道更好的方法?

现在,虽然追加非常简单,但 随机 数据块的删除并不那么简单。我想做的是转移数据以覆盖已删除的消息。我只是将消息右侧的所有字节移到它的开头。

总的来说,这是正确的策略,还是有人会提出其他建议或改进这个概念?

【问题讨论】:

在文件中移动数据是个坏主意。如果您的块的顺序不重要,您可以将最后一个块移动到已删除块的位置(考虑到块具有相同大小的事实)。否则,您应该添加一种方法将块标记为已删除,并在您有明显稀疏的块时进行清理。 是因为性能原因还是其他原因导致移位不好? 主要是性能。但这也与您在操作之间中断应用程序的情况下的安全意图相矛盾。 好吧,任何超过一个字节更改的标记无论如何都会与此相矛盾 - 标记为已删除/仅移动一个块仍然可能被中断,对吗? 压缩类似于移位。不同之处在于,在一种情况下,您必须复制可能很大的文件内容以容纳单个已删除的块,而在另一种情况下,您必须复制一些剩余的块以容纳大量删除。但这只是评论而不是答案…… 【参考方案1】:

您可以在FileChannel(或File 或其他任何东西,只要您知道它是您的文件)之上使用自定义包装类,并使其提供映射,甚至自己编写映射。

在这个类中,跟踪大小。使其实现Closeable。当你 .close() 它时,取消映射所有内容并截断/扩展为适当的大小。

【讨论】:

对此的主要担忧是jvm可能会崩溃,并且文件将处于不一致状态,因此有一种方法可以不断标记文件的结尾(使用我描述的标记)似乎更安全一些 好吧,鉴于你的文件大小(相当小),你也可以让这个类写入一个临时文件并重命名为close()上的原始文件

以上是关于Java NIO - MappedByteBuffer 的截断的主要内容,如果未能解决你的问题,请参考以下文章

Java:NIO 和 NIO.2 到底有啥区别?

Java NIO:NIO概述

Java NIO系列教程 Java NIO与IO

Java NIO2:NIO概述

Java NIO系列教程 Java NIO与IO

Java Nio 十Java NIO Files