我正在读取一个较大的tsv文件(〜40G),并试图通过逐行读取并仅将某些行打印到新文件中来对其进行修剪。但是,我不断收到以下异常:

java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:2894)
    at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:117)
    at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:532)
    at java.lang.StringBuffer.append(StringBuffer.java:323)
    at java.io.BufferedReader.readLine(BufferedReader.java:362)
    at java.io.BufferedReader.readLine(BufferedReader.java:379)

下面是代码的主要部分。我指定缓冲区大小为8192,以防万一。一旦达到缓冲区大小限制,Java不会清除缓冲区吗?我看不出是什么原因导致这里的大量内存使用。我试图增加堆大小,但没有任何区别(带有4GB RAM的机器)。我还尝试每X行刷新一次输出文件,但这也无济于事。我在想,也许我需要致电GC,但这听起来不对。

有什么想法吗?非常感谢。
顺便说一句-我知道我只应该调用trim()一次,存储它,然后使用它。
Set<String> set = new HashSet<String>();
set.add("A-B");
...
...
static public void main(String[] args) throws Exception
{
   BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(inputFile),"UTF-8"), 8192);
   PrintStream output = new PrintStream(outputFile, "UTF-8");

   String line = reader.readLine();
   while(line!=null){
        String[] fields = line.split("\t");
        if( set.contains(fields[0].trim()+"-"+fields[1].trim()) )
            output.println((fields[0].trim()+"-"+fields[1].trim()));

        line = reader.readLine();
   }

output.close();

}

最佳答案

最有可能的是,该文件没有行终止符,因此阅读器只会不断扩大它的StringBuffer的范围,直到它用尽内存为止。

解决方案是使用读取器的“读取”方法一次读取固定数量的字节,然后在较小的缓冲区中查找新行(或其他解析标记)。

关于java - 用Java读取大文件-Java堆空间,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5890616/

10-11 22:54
查看更多