读取文件(> 150MB)并将文件内容作为ByteArrayOutputStream返回

时间:2012-05-10 11:55:59

标签: java fast-esp

我正在尝试读取大文件(> 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堆大小,但它仍然发生。有人可以帮助解决这个问题。

5 个答案:

答案 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空间。