Java:内存高效的ByteArrayOutputStream

use*_*887 16 java bytearray memory-mapped-files bytearrayoutputstream

我在磁盘中有一个40MB的文件,我需要使用字节数组将其"映射"到内存中.

起初,我认为将文件写入ByteArrayOutputStream是最好的方法,但我发现在复制操作期间的某个时刻需要大约160MB的堆空间.

如果不使用RAM文件大小的三倍,有人知道更好的方法吗?

更新:感谢您的回答.我注意到我可以减少内存消耗,稍微告诉ByteArrayOutputStream的初始大小要比原始文件大小稍大一些(使用我的代码强制重新分配的确切大小,得到检查原因).

还有另一个高内存点:当我用ByteArrayOutputStream.toByteArray返回byte []时.看看它的源代码,我可以看到它正在克隆数组:

public synchronized byte toByteArray()[] {
    return Arrays.copyOf(buf, count);
}
Run Code Online (Sandbox Code Playgroud)

我想我可以扩展ByteArrayOutputStream并重写此方法,以便直接返回原始数组.这里有没有潜在的危险,因为流和字节数组不会被多次使用?

JB *_*zet 13

MappedByteBuffer 可能就是你要找的东西.

我很惊讶它需要这么多RAM来读取内存中的文件.你ByteArrayOutputStream有没有适当的容量建造?如果还没有,则流可以在接近40 MB的末尾时分配一个新的字节数组,这意味着您将拥有一个39 MB的完整缓冲区和两倍大小的新缓冲区.而如果流具有适当的容量,则不会有任何重新分配(更快),也不会浪费内存.


Jon*_*eet 10

ByteArrayOutputStream只要在构造函数中指定适当的大小,就应该没问题.当你打电话时它仍然会创建一个副本toByteArray,但这只是暂时的.你真的介意记忆短暂上升吗?

或者,如果您已经知道要开始的大小,则只需创建一个字节数组,然后重复读FileInputStream入该缓冲区,直到获得所有数据.


Joa*_*uer 5

如果你真的想将文件映射到内存中,那么a FileChannel是适当的机制.

如果您只想将文件读入一个简单的文件byte[](并且不需要对该数组进行更改以反映回文件),那么只需byte[]从正常文件中读取适当大小即可FileInputStream.

番石榴Files.toByteArray()哪些做了所有为你.