2011-07-28 91 views
14

我有一个java服务器应用程序下载CSV文件并解析它。解析可能需要5到45分钟,并且每小时发生一次。此方法是应用程序的瓶颈,因此它不是过早的优化。到目前为止的代码:快速CSV解析

 client.executeMethod(method); 
     InputStream in = method.getResponseBodyAsStream(); // this is http stream 

     String line; 
     String[] record; 

     reader = new BufferedReader(new InputStreamReader(in), 65536); 

     try { 
      // read the header line 
      line = reader.readLine(); 
      // some code 
      while ((line = reader.readLine()) != null) { 
       // more code 

       line = line.replaceAll("\"\"", "\"NULL\""); 

       // Now remove all of the quotes 
       line = line.replaceAll("\"", "");  


       if (!line.startsWith("ERROR"){ 
        //bla bla 
        continue; 
       } 

       record = line.split(","); 
       //more error handling 
       // build the object and put it in HashMap 
     } 
     //exceptions handling, closing connection and reader 

是否有任何现有的库,可以帮助我加快速度?我可以改进现有的代码吗?

+2

文件有多大?你有没有尝试分析你的代码?这会给你提供瓶颈和清晰的想法。如果您的网络成为主要问题,我不会感到惊讶。也可以查看http://commons.apache.org/sandbox/csv/而不是自己构建解析器。 – joostschouten

+0

我现在正在分析,我知道大部分时间都是由网络连接引起的。我想首先改善解析,因为在网络中我需要改变架构。 (我的估计是,更快的解析可以提高10-15%的加载时间)。 –

+0

听起来公平。请使用csv解析器,因为这些解析器已经过优化,您肯定会遇到逃跑和国际化的问题,您不必担心。祝你好运。 – joostschouten

回答

18

阿帕奇百科全书CSV

你见过Apache Commons CSV

买者在使用split

另一件事要记住的是,split只返回数据的视图,这意味着原来line对象不符合垃圾收集,同时有任何的参考其观点。也许制作一个防御副本会有所帮助? (Java bug report

+0

对于错误+1,我会尝试Apache。 –

2

opencsv

你应该看看OpenCSV。我希望他们有性能优化。

+0

我们对opencsv有非常不好的体验。我们发现它既慢又有问题。最终浪费了半天,并将其全部替换掉​​。 – Guy

+0

好的...您可能想要添加更多详细信息以使此信息相关。你有什么问题?你使用了哪个版本?你选择了哪个其他框架?我只是想知道,因为我在多个项目中看到它做得很好。 – Kai

+0

主要问题是它返回了错误的字段数(即,我在10字段行上得到了2字段字符串[]]。我从来没有明白为什么会发生,但我猜它与某些坏的utf-8解析有关。 我用自己的逐行读取字符串String.split取代了它(我意识到这里有一些内存方面的考虑因素),最终运行速度提高了15%-30%。 我正在使用opencs v2.3(java) – Guy

5

除了上面提出的建议,我认为你可以尝试使用一些线程和并发来改进你的代码。

以下是简要的分析和建议的解决方案

  1. 从代码看来,你是在网络上(最可能是Apache的共HttpClient的LIB)读取数据。
  2. 您需要确保您所说的瓶颈不在网络上的数据传输中。
  3. 看到的一种方法就是将数据转储到某个文件中(无需解析)并查看需要多少。这会让你知道在解析中实际花费了多少时间(与当前的观察相比)。
  4. 现在看看如何使用java.util.concurrent包。您可以使用的一些链接是(1,2
  5. 您可以做的是您在for循环中执行的任务可以在线程中执行。
  6. 使用线程池和并发将大大提高性能。

虽然解决方案需要一些努力,但最终这会帮助你。

+0

如果瓶颈转移到网络上,您应该考虑指定gzip头 –