繁体   English   中英

Java-读取巨大的CSV文件时出现OutofMemoryError

[英]Java - OutofMemoryError while reading a huge csv file

我想通过Java读取庞大的csv文件。 它包括75,000,000行。 问题是,即使我用最大的xmsxmx限制,我得到:`java.lang.OutOfMemoryError(GC开销超过限制),它显示了该行导致错误:

String[][] matrix = new String[counterRow][counterCol];

我做了一些测试,发现我可以很好地阅读15,000,000行。 因此,我开始使用这种代码:

String csvFile = "myfile.csv";
List<String[]> rowList = new ArrayList();
String line = "";
String cvsSplitBy = ",";
BufferedReader br = null;
try {
    int counterRow = 0, counterCol = 12, id = 0;
    br = new BufferedReader(new FileReader(csvFile));
    while ((line = br.readLine()) != null) { 
        String[] object = line.split(cvsSplitBy);
        rowList.add(object); 
        counterRow++;
        if (counterRow % 15000000 ==0) {
            String[][] matrix = new String[counterRow][counterCol];
            .. do processes ..
            SaveAsCSV(matrix,id);
            counterRow=0; id++; rowList.clear();
        }
    }
}
...

在这里,它很好地写入了第一行15.000.000行,但是在第二次尝试中,尽管counterRow为15,000,000,但它再次给出了相同的错误。

总之,我需要在Java中读取包含75,000,000行(约5 GB)的csv文件,并在对其记录进行某些处理后保存一个或多个新的csv文件。

我怎么解决这个问题?

谢谢

编辑:我也使用rowList.clear()伙计们,忘了在这里指定。 抱歉。

编辑2:我的朋友们,我不需要将所有文件都放在内存中。 我如何才能部分地阅读它。 实际上,这就是我尝试使用if(counterRow%15000000 == 0)进行的操作。 正确的方法是什么?

您可以逐行阅读各行,然后进行处理,直到您阅读了整个文件

String encoding = "UTF-8";
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("/bigfile.txt"), encoding));
String line;
while ((line = br.readLine()) != null) {
   // process the line.
}
br.close();

这不应该只是为了确保您立即进行,并且不要将其存储在循环外的变量中

问题不是您没有足够的内存,问题“超出了GC开销限制”意味着垃圾收集花费的时间太长。 您不能通过分配更多的内存来解决此问题,而只能使用-XX:-UseGCOverheadLimit 也就是说,如果您确实要在内存中存储那么多数据。

请参见例如如何使用maven jvmArg解决“超出了GC开销限制”?

或使用彼得·劳里(Peter Lawrey)的内存映射HugeCollection: http ://vanillajava.blogspot.be/2011/08/added-memory-mapped-support-to.html?q=huge+collections:如果内存已满,它将写入磁盘。

也许你忘了打电话

rowList.clear();

counterRow=0; id++;

当您的应用程序几乎耗尽了所有可用内存并且GC反复无法清除它时,将显示“ java.lang.OutOfMemoryError:超出GC开销限制”错误。

我强烈建议您不要执行上述建议的解决方案-指定-XX:-UseGCOverheadLimit 而不是解决问题,您只是推迟了不可避免的事情:应用程序内存不足,需要修复。 指定此选项仅会掩盖原始的“ java.lang.OutOfMemoryError:GC超出开销限制 ”错误,并显示更熟悉的消息“ java.lang.OutOfMemoryError:Java堆空间 ”。

在您的情况下,可能的解决方案大致归结为两个合理的选择-增加堆空间(-Xmx参数)或通过小批量读取文件来减少代码的堆消耗。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM