在Java中读取大文件 - Java堆空间

use*_*336 7 java file-io file

我正在读一个大的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)
Run Code Online (Sandbox Code Playgroud)

下面是代码的主要部分.为了以防万一,我将缓冲区大小指定为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();

}
Run Code Online (Sandbox Code Playgroud)

小智 17

最有可能的是,该文件没有行终止符,所以读者只是不断增长它的StringBuffer无限制,直到它耗尽内存.

解决方案是使用阅读器的"读取"方法一次读取固定数量的字节,然后在较小的缓冲区内查找新行(或其他解析令牌).