Far*_*deh 5 java csv performance android
我注意到java.util.Scanner在读取大文件时使用非常慢(在我的例子中是CSV文件).
我想改变我目前正在阅读文件的方式,以提高性能.以下是我目前的情况.请注意,我正在为Android开发:
InputStreamReader inputStreamReader;
try {
inputStreamReader = new InputStreamReader(context.getAssets().open("MyFile.csv"));
Scanner inputStream = new Scanner(inputStreamReader);
inputStream.nextLine(); // Ignores the first line
while (inputStream.hasNext()) {
String data = inputStream.nextLine(); // Gets a whole line
String[] line = data.split(","); // Splits the line up into a string array
if (line.length > 1) {
// Do stuff, e.g:
String value = line[1];
}
}
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
Run Code Online (Sandbox Code Playgroud)
使用Traceview,我设法发现主要的性能问题,特别是:java.util.Scanner.nextLine()和java.util.Scanner.hasNext().
我已经看过其他问题了(比如这个),我遇到过一些CSV读者,比如Apache Commons CSV,但他们似乎没有太多关于如何使用它们的信息,而且我是不知道他们会多快多少.
我也听说过使用FileReader和BufferedReader像回答这一个,但同样,我不知道改进是否会显著.
我的文件大约有30,000行,并且使用我目前的代码(上图),从大约600行读取值至少需要1分钟,所以我没有时间读取值需要多长时间从超过2,000行下来,但有时,在阅读信息时,Android应用程序变得无法响应并崩溃.
虽然我可以简单地更改部分代码并亲自查看,但我想知道是否有更快的替代方法,我没有提及,或者我是否应该使用FileReader和BufferedReader.将大文件拆分成较小的文件会更快,并根据我想要检索的信息选择要读取的文件吗?最好,我也想知道为什么最快的方法是最快的(即什么使它快).
uniVocity 解析器拥有最快的 CSV 解析器(比 OpenCSV 快 2 倍,比 Apache Commons CSV 快 3 倍),具有许多独特的功能。
这是一个关于如何使用它的简单示例:
CsvParserSettings settings = new CsvParserSettings(); // many options here, have a look at the tutorial
CsvParser parser = new CsvParser(settings);
// parses all rows in one go
List<String[]> allRows = parser.parseAll(new FileReader(new File("your/file.csv")));
Run Code Online (Sandbox Code Playgroud)
为了加快流程,您可以选择您感兴趣的列:
parserSettings.selectFields("Column X", "Column A", "Column Y");
Run Code Online (Sandbox Code Playgroud)
通常,您应该能够在 2 秒左右解析 400 万行。通过列选择,速度将提高大约 30%。
如果您使用RowProcessor ,它会更快。有许多开箱即用的实现,用于处理对象、POJOS 等的转换。文档解释了所有可用功能。它是这样工作的:
// let's get the values of all columns using a column processor
ColumnProcessor rowProcessor = new ColumnProcessor();
parserSettings.setRowProcessor(rowProcessor);
//the parse() method will submit all rows to the row processor
parser.parse(new FileReader(new File("/examples/example.csv")));
//get the result from your row processor:
Map<String, List<String>> columnValues = rowProcessor.getColumnValuesAsMapOfNames();
Run Code Online (Sandbox Code Playgroud)
我们还建立了一个简单的速度对比的项目在这里。
您的代码适合加载大文件。但是,当操作的时间比您预期的长时,最好在任务中而不是在 UI 线程中执行它,以防止响应能力不足。
AsyncTask 类有助于做到这一点:
private class LoadFilesTask extends AsyncTask<String, Integer, Long> {
protected Long doInBackground(String... str) {
long lineNumber = 0;
InputStreamReader inputStreamReader;
try {
inputStreamReader = new
InputStreamReader(context.getAssets().open(str[0]));
Scanner inputStream = new Scanner(inputStreamReader);
inputStream.nextLine(); // Ignores the first line
while (inputStream.hasNext()) {
lineNumber++;
String data = inputStream.nextLine(); // Gets a whole line
String[] line = data.split(","); // Splits the line up into a string array
if (line.length > 1) {
// Do stuff, e.g:
String value = line[1];
}
}
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
return lineNumber;
}
//If you need to show the progress use this method
protected void onProgressUpdate(Integer... progress) {
setYourCustomProgressPercent(progress[0]);
}
//This method is triggered at the end of the process, in your case when the loading has finished
protected void onPostExecute(Long result) {
showDialog("File Loaded: " + result + " lines");
}
}
Run Code Online (Sandbox Code Playgroud)
...并执行为:
new LoadFilesTask().execute("MyFile.csv");
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8424 次 |
| 最近记录: |