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



我正在读取一个大的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,直到它耗尽内存。

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

您确定文件中的"行"由换行符分隔吗?

我有三个理论:

  • 输入文件不是UTF-8,而是某种不确定的二进制格式,当以UTF-8读取时会导致超长的行。

  • 该文件包含一些超长的"行"。。。或者根本没有断线。

  • 代码中发生了一些您没有向我们显示的其他事情;例如,您正在向set添加新元素。


帮助诊断:

  • 使用od(在UNIX/LINUX上(之类的工具来确认输入文件是否真的包含有效的行终止符;即CR、NL或CR NL
  • 使用一些工具来检查文件是否为有效的UTF-8
  • 在代码中添加一个静态行计数器,当应用程序出现OOME时,打印出行计数器的值
  • 记录到目前为止看到的最长的一行,并在收到OOME时打印出来

请注意,您对trim的使用稍不理想与此问题无关。

一种可能性是在垃圾收集期间堆空间不足。Hotspot JVM默认使用并行收集器,这意味着您的应用程序分配对象的速度可能快于收集器回收对象的速度。通过快速分配和丢弃,我已经能够对据称只有10K个活动(小(对象造成OutOfMemoryError。

您可以尝试使用带有选项-XX:+UseSerialGC的旧的(1.5之前的(串行采集器。您还可以使用其他几个"扩展"选项来调整集合。

您可能需要尝试从循环中删除String[] fields声明。当您在每个循环中创建一个新数组时。你可以重复使用旧的,对吧?

相关内容

  • 没有找到相关文章

最新更新