快速CSV解析
我有一个java服务器应用程序,下载CSV文件并解析它。 解析可能需要5到45分钟,并且每小时发生一次。这种方法是应用程序的瓶颈,因此它不是过早优化。 到目前为止的代码:
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
是否有任何现有的图书馆可以帮助我加快速度? 我可以改进现有代码吗?
Apache Commons CSV
你见过Apache Commons CSV吗?
警告使用split
请记住, split
只返回数据视图,这意味着原始line
对象不符合垃圾回收的条件,同时引用其任何视图。 制作防御性副本可能会有所帮助吗? ( Java bug报告 )
在对包含逗号的转义CSV列进行分组时,它也不可靠
opencsv
看看opencsv 。
这篇博客文章, opencsv是一个简单的CSV解析器 ,具有示例用法。
除了上面提出的建议之外,我认为你可以尝试通过使用一些线程和并发来改进你的代码。
以下是简要分析和建议的解决方案
- 从代码中看来,您正在通过网络读取数据(最可能是apache-common-httpclient lib)。
- 您需要确保您所说的瓶颈不在网络上的数据传输中。
- 一种方法是将数据转储到某个文件中(不进行解析),看看它需要多少。 这将让您了解实际花费在解析上的时间(与当前观察相比)。
- 现在看看如何使用java.util.concurrent包。 您可以使用的一些链接是( 1,2 )
- 你可以做的是你在for循环中执行的任务可以在一个线程中执行。
- 使用线程池和并发将极大地提高您的性能。
虽然解决方案需要一些努力,但最终这将对您有所帮助。
你的代码的问题是它使用replaceAll和split是非常昂贵的操作。 你绝对应该考虑使用csv解析器/阅读器进行一次解析。
github上有一个基准测试
https://github.com/uniVocity/csv-parsers-comparison
不幸的是,它在java 6下运行。在java 7和8下,数字略有不同。我正在尝试获取更多不同文件大小的详细数据,但它正在进行中
请参阅https://github.com/arnaudroger/csv-parsers-comparison
opencsv
你应该看一下OpenCSV 。 我希望他们有性能优化。