读取大文件时出现Java堆空间错误

时间:2013-07-01 18:23:47

标签: java file-io inputstream heap-memory apache-commons-io

我正在尝试将整个文件作为字符串对象加载到内存中。但是在应用程序结束后,我的内存不会被释放回垃圾收集器。我知道在内存中读取整个文件很糟糕,不管我有没有将数据发送到另一个类,任何人都可以帮助我如何只是一个流而不是将整个代码加载到内存中,如果没有,任何人都可以说我现在的代码有什么问题

private   String processFile(FileItemStream item) throws IOException{

        InputStream is=null;

        try{
            is=item.openStream();
            return IOUtils.toString(is, "UTF-8");
        }
        finally {

            IOUtils.closeQuietly(is);

        }

    }




data=processFile(item)//method call
SomeClass(data);//passing the data string to this class

3 个答案:

答案 0 :(得分:1)

您应该将is传递到需要数据的类中。只要您没有同时阅读is的所有内容,就不会耗尽所有记忆。将您的代码更改为:

InputStream is = null;
try {
    is = getFileAsStream(item);
    SomeClass(is)  //of course this probably doesn't compile, I'm just using your code sample
} finally {
    //close is
}

答案 1 :(得分:1)

这取决于您可以使用的API。如果他们的API允许您一次处理一个字节数据数组,那么您应该将一个块读入缓冲区并将其发送到该应用程序。如果它允许你传入一个InputStream,那么你应该这样做。

如果API不允许您执行上述操作之一,那么唯一可以做的就是增加Java可以使用的内存量。为此,使用-Xmx512m开关启动Java,其中512是可以分配给Java的内存量。

答案 2 :(得分:0)

如果您真的无法更改要调用的API以获取除字符串之外的内容,那么您需要通过为JVM提供更多内存来解决此问题。这可以通过向JVM发送参数来更改。

-Xmx<size>

例如,您可以使用这样的设置为JVM提供最大2GB的堆

-Xmx2g

虽然如果您使用的API接受String作为参数并且正在尝试传递一个数GB的字符串,那么您几乎肯定会错误地使用它们的API。如果某人构建了一个期望大量数据的API,则他们不会使用单个字符串作为参数来构建它。祝你好运。