读取大型文本文件时发生Java OutOfMemoryError

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (26)

我是Java新手,正在阅读非常大的文件,需要一些帮助来理解问题并解决它。我们已经得到了一些遗留代码,必须进行优化才能使其正常运行。文件大小只能在10mb到10gb之间变化。只有当文件启动超过800mb大小时才会出现问题。

InputStream inFileReader = channelSFtp.get(path); // file reading from ssh.
byte[] localbuffer = new byte[2048];
ByteArrayOutputStream bArrStream = new ByteArrayOutputStream();

int i = 0;
while (-1 != (i = inFileReader.read(buffer))) {
bArrStream.write(localbuffer, 0, i);
}

byte[] data = bArrStream.toByteArray();
inFileReader.close();
bos.close();

我们正在收到错误

java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:2271)
    at java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:113)
    at java.io.ByteArrayOutputStream.ensureCapacity(ByteArrayOutputStream.java:93)
    at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:140)

任何帮助,将不胜感激?

提问于
用户回答回答于

尽管可以增加JVM内存限制,但它并不是必需的,并且可以分配一个像10GB这样的巨大内存来处理文件,这听起来有点矫枉过正并且是资源密集型的。

目前,您正在使用一个“ByteArrayOutputStream”来保持内部存储器的数据。代码中的这行代码将最后读取的2KB文件块添加到此缓冲区的末尾:

bArrStream.write(localbuffer, 0, i);

bArrStream不断增长并最终耗尽内存。

相反,您应该重新组织您的算法并以流式处理文件:

InputStream inFileReader = channelSFtp.get(path); // file reading from ssh.
byte[] localbuffer = new byte[2048];

int i = 0;
while (-1 != (i = inFileReader.read(buffer))) {
    //Deal with the current read 2KB file chunk here
}

inFileReader.close();
用户回答回答于

尝试使用java.nio.MappedByteBuffer

http://docs.oracle.com/javase/7/docs/api/java/nio/MappedByteBuffer.html

您可以将文件的内容映射到内存,而无需手动复制。高级操作系统提供内存映射,Java有API来利用该功能。

如果我的理解是正确的,内存映射不会将文件的全部内容加载到内存中(意思是“根据需要部分加载和卸载”),所以我猜测10GB文件不会占用内存。

扫码关注云+社区