处理 ByteArrayInputStream 中的大文件 (>2GB)



我从其他方法获得一个非常大的文件(>2.5GB) ByteArrayInputStream格式的数据。我必须将此数据以InputStream格式传递给另一个方法。我编写了以下代码,对于较小的文件执行良好,但对于大于2GB的大文件则失败。

ByteArrayInputStream bais = null;
bais = method_Returns_FIle_In_ByteArrayInputStream_Format();
InputStream is = bais;
method_Where_To_send_Data_In_InputStream_Format(is);

但是我的代码在第二行本身就坏了,给出以下错误:

java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3236)
at java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:118)
at java.io.ByteArrayOutputStream.ensureCapacity(ByteArrayOutputStream.java:93)
at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:153)

已经尝试增加Java堆空间大小(-Xms和-Xmx)。

欢迎提出任何建议。

我从其他方法获得一个非常大的文件(>2.5GB) ByteArrayInputStream格式的数据。

战争以另一种方式失败。如果你不能改变"另一种方法",那你就倒霉了。你在这里什么都做不了。ByteArrayInputStream的定义是完全是内存事务,如果2.5GB的数据包含该流的全部内容,那么BAIS至少需要2.5GB的内存。你无能为力.

修复方法是去那个方法并修复它。它绝对没有理由以BAIS的形式发送这些信息。InputStream的"点"在名称中:它是数据。

如果您无法更改它,并且64位VM上的-Xmx8g无法修复它,那么就没有什么可做的了。

您不应该尝试加载整个文件,然后从内存中读取它。

try (InputStream is = method_Returns_FIle_In_InputStream_Format()) {
method_Where_To_send_Data_In_InputStream_Format(is);
}

上面使用的try-with-resources会自动关闭is,即使在出现异常、break或return时也是如此。

文件读取方法可以执行

Path path = Paths.get("phantasies.log");
return Files.newInputStream(path);

当想要对文件输入做一些额外的处理时,可以将InputStream包装在FilterInputStream的自定义子文件中。

这也表明根据接口(InputStream)而不是实际实现(ByteArrayInputStream)进行编程更好。

如果ByteArrayInputStream源于收集OutputStream,则应该使用java的管道I/O:PipedInputStream&PipedOutputStream-与额外的Thread.

或者可以使用压缩来减少内存的大小,GZipInputStream/GZipOutputStream.

最新更新