我想通过Java阅读一个巨大的csv
文件。它包括75,000,000行。问题是,即使我使用最大xms
和xmx
限制,我得到:`java.lang.OutOfMemoryError(超出GC开销限制),它显示此行导致错误:< / p>
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)。它的正确方法是什么?答案 0 :(得分:4)
您可以单独阅读这些行,然后进行处理,直到您阅读完整个文件
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();
这不应该是fubar只是确保你立即处理它并且不要将它存储在循环外的变量中
答案 1 :(得分:0)
问题不在于您没有足够的内存,问题&#34; GC开销限制已超过&#34;意味着垃圾收集时间过长。您无法通过分配更多内存来解决此问题,但只能使用-XX:-UseGCOverheadLimit
。也就是说,如果你真的想在内存中存储那么多数据。
参见例如How to solve "GC overhead limit exceeded" using maven jvmArg?
或者使用peter lawrey的内存映射HugeCollections:http://vanillajava.blogspot.be/2011/08/added-memory-mapped-support-to.html?q=huge+collections:如果内存已满,它会写入磁盘。
答案 2 :(得分:0)
也许你忘了打电话了
rowList.clear();
后
counterRow=0; id++;
答案 3 :(得分:0)
当您的应用程序耗尽了几乎所有可用内存并且GC多次无法清除它时,将显示“java.lang.OutOfMemoryError:GC开销超出限制”错误。
上面推荐的解决方案 - 指定 -XX:-UseGCOverheadLimit 是我强烈建议不要做的事情。而不是解决问题,你只是推迟不可避免的:应用程序内存不足,需要修复。指定此选项只会掩盖原始的“ java.lang.OutOfMemoryError:GC开销限制超出”错误,其中包含更为熟悉的消息“ java.lang.OutOfMemoryError:Java堆空间”
在您的情况下,可能的解决方案几乎归结为两个合理的替代方案 - 增加堆空间(-Xmx参数)或通过以较小批量读取文件来减少代码的堆消耗。