我正在尝试读取大文件(> 150MB)并将文件内容作为ByteArrayOutputStream
返回。这是我的代码......
private ByteArrayOutputStream readfileContent(String url) throws IOException{
log.info("Entering readfileContent ");
ByteArrayOutputStream writer=null;
FileInputStream reader=null;
try{
reader = new FileInputStream(url);
writer = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int bytesRead = reader.read(buffer);
while (bytesRead = > -1) {
writer.write(buffer, 0, bytesRead);
buffer = new byte[1024];
}
}
finally {
writer.close();
}
log.info("Exiting readfileContent ");
return writer;
}
我得到java.lang.OutOfMemoryError: Java heap space exception
。我试过增加java堆大小,但它仍然发生。有人可以帮助解决这个问题。
答案 0 :(得分:1)
您应该返回BufferedInputStream
并让调用者从中读取。你正在做的是将整个文件作为ByteArrayOutputStream
复制到内存中。
您的问题缺少您要对文件内容执行的操作。没有它我们只能猜测。有一个ServletOutputStream
被注释掉了。你最初想写这个吗?写入此代替ByteArrayOutputStream
应该正常工作。
答案 1 :(得分:1)
while循环中有错误。将其更改为
while (bytesRead >= -1) {
writer.write(buffer, 0, bytesRead);
bytesRead = reader.read(buffer);
}
另请不要忘记关闭reader
。
(它仍然需要相当大的内存。)
答案 2 :(得分:0)
由于您知道将要读取多少字节,因此可以通过创建具有大小的ByteArrayOutputStream
来节省时间和空间。这将节省“增长”ByteArrayOutputStream
后备存储的时间和空间开销。 (我没有查看代码,但它可能使用与StringBuilder
相同的策略;即每次耗尽时将分配加倍。该策略最终可能会在峰值时使用最多3倍的文件大小使用情况。)
(坦率地说,当你知道大小似乎有点无意义时,将输出放入ByteArrayOutputStream
。只需将字节数组分配得足够大并直接读入它。)
除此之外,答案是你需要扩大堆。
答案 3 :(得分:0)
你的方法将至少使用与文件相同的内存量,但由于ByteArrayOutputStream使用字节数组作为存储,因此它可能需要自己调整150,000次(150 meg / 1024k缓冲区),这是效率不高。将堆大小提高到2 *你的文件大小并将buf的大小增加到更大的大小可能允许它运行,但正如其他海报所说的那样,在你去的时候读取文件要好得多,而不是在作为一个字符串。
答案 4 :(得分:0)
由于主机上没有足够的连续虚拟内存,我在Windows中看到了C#中的类似问题。如果您在Windows上,可以尝试增加VM空间。