2017-05-06 185 views
3

我正在尝试使用Java读取1,000,000行CSV文件。我正在使用OpenCSV库,它可以在30,000行的较小文件上正常工作。在不到半秒的时间内处理它。但是当我尝试从一百万行文件中读取时,它永远不会结束。在Java中读取大型CSV文件

现在我测试看看,什么时候会真正停止,并用自己的二进制搜索的版本,我第一次尝试阅读500K线,然后250K,等等,我发现它容易读数145k行,在0.5-0.7sec,而150k甚至没有完成。

我已经彻底搜索过,发现了几个我在代码中使用的解决方案,例如使用BufferedReader,BufferedInputStream等,但没有一个解决了它。仍然失败145-150k线。

这是我的代码的相关部分(交换150000与145000是什么原因导致的程序在< 1秒执行):

try { 
     // BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("myFile.csv")); 
     CSVReader csvReader = new CSVReader(new InputStreamReader 
       (new BufferedInputStream(new FileInputStream("myFile.csv"), 8192 * 32))); 
     try { 
      int count = 0; 
      String[] line; 
      long timeStart = System.nanoTime(); 
      while((line = csvReader.readNext()) != null){ 
       count ++; 
       if(count >= 150000){ 
        break; 
       } 
      } 
      long timeEnd = System.nanoTime(); 
      System.out.println("Count: " + count); 
      System.out.println("Time: " + (timeEnd - timeStart) * 1.0/1000000000 + " sec"); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } catch (FileNotFoundException e) { 
     System.out.println("File not found"); 
    } 

正如你所看到的,我已尝试设置一个更大的缓冲大小也是如此。我尝试过Readers,Input Streams等各种组合,没有什么真正有所作为。

我想知道我该怎么做?有没有办法阅读,一次说10万行,然后继续阅读下一个100K?

此外,我接受任何其他解决方案,其中不一定包含OpenCSV库。我只是用它来简单地解析一个csv文件。

+0

当你说'永远不会结束'......它到底是什么?死锁,内存不足等......使用调试器来查看它到底是什么,或者在循环中放入一些系统信息以查看它是否仍在处理中,但速度很慢? – Adam

回答

2

也许问题不在于CSV文件中的行数,而是它的内容。也许有一些数据在145k到150k之间,这会导致你的应用程序永远不会完成。

如果您复制文件中的第一行145k行并将其粘贴到新的CSV文件中,直到它有1m行,您可以检查它。如果您的应用程序可以处理这个新文件,那么问题出现在数据中,而不是行数。

3

我只是看了一下OpenCSV的实现,我没有看到任何可以解释这种行为的东西,只是因为文件很大并且包含大量记录。

但OpenCSV能够处理多行数据,从网站:

处理带有嵌入式回车(跨多行即项)引用条目。

我认为在您的情况下,有一条记录 - 第150k条记录的某处 - 包含错误的引用条目。默认的引用字符是"。这可能是一个纪录,如:

value,value,"badvalue,value 
value,value,value,value 

在这种情况下,所使用的OpenCSV IST设置为挂起状态,即读取记录继续在下一行的解析器。并且拨打CSVReader.readNext()会尝试读取尽可能多的行以完成csv记录。如果没有不匹配错位的引用字符,它将读取和读取并读取,直到缓冲区耗尽或发生其他错误。

要查找记录,您可以像读取文件一样读取记录,对记录进行计数并打印出当前计数。这会给你最后一个有效记录的编号,然后会像现在一样停止/挂起。

然后,我会写一个新的程序,它只是逐行读取文件(不使用CSVParser,只是简单的行),并跳过你认为很好的行数。然后从那里打印大约10行,并且您有一些数据要分析。

+0

我同意P.J.和Marat的问题是数据。如果你想继续使用与上面相同的程序,我会考虑以二进制方式缩小数字(145K,所以使用147K,然后是148K,等等),以便在开始永久使用时缩小范围。然后,您可以查看实际文件中的该行(以及上方/下方的行),以查看数据开始变形的位置。 –