我想读取包含数百万行的csv文件,并使用我的决策树算法的属性.我的代码如下:
String csvFile = "myfile.csv";
List<String[]> rowList = new ArrayList();
String line = "";
String cvsSplitBy = ",";
String encoding = "UTF-8";
BufferedReader br2 = null;
try {
int counterRow = 0;
br2 = new BufferedReader(new InputStreamReader(new FileInputStream(csvFile), encoding));
while ((line = br2.readLine()) != null) {
line=line.replaceAll(",,", ",NA,");
String[] object = line.split(cvsSplitBy);
rowList.add(object);
counterRow++;
}
System.out.println("counterRow is: "+counterRow);
for(int i=1;i<rowList.size();i++){
try{
//this method includes many if elses only.
ImplementDecisionTreeRulesFor2012(rowList.get(i)[0],rowList.get(i)[1],rowList.get(i)[2],rowList.get(i)[3],rowList.get(i)[4],rowList.get(i)[5],rowList.get(i)[6]);
}
catch(Exception ex){
System.out.printlnt("Exception occurred");
}
}
}
catch(Exception ex){
System.out.println("fix"+ex);
}
Run Code Online (Sandbox Code Playgroud)
当csv文件的大小不大时,它工作正常.但是,确实很大.因此我需要另一种方法来更快地读取csv.有什么建议吗?赞赏,谢谢.
lau*_*une 10
在这个片段中,我看到两个问题会让你大大减慢速度:
while ((line = br2.readLine()) != null) {
line=line.replaceAll(",,", ",NA,");
String[] object = line.split(cvsSplitBy);
rowList.add(object);
counterRow++;
}
Run Code Online (Sandbox Code Playgroud)
首先,rowList以默认容量开始,并且必须多次增加,总是导致旧的底层数组的副本为新的.
然而,更糟糕的是,数据过度爆炸成String []对象.只有在为该行调用ImplementDecisionTreeRulesFor2012时才需要列/单元格- 当您读取该文件并处理所有其他行时,并不是所有时间.将分组(或更好的内容,如注释所示)移动到第二行.
(即使你能负担得起内存,创建许多对象也很糟糕.)
也许最好在阅读"百万"时调用ImplementDecisionTreeRulesFor2012?它会完全避免使用rowList ArrayList.
稍后 推迟拆分可将1000万行的执行时间从1m8.262s(当程序用完堆空间时)减少到13.067s.
如果您在调用Implp ... 2012之前没有被强制读取所有行,则时间减少到4.902s.
最后写下拆分并手工更换:
String[] object = new String[7];
//...read...
String x = line + ",";
int iPos = 0;
int iStr = 0;
int iNext = -1;
while( (iNext = x.indexOf( ',', iPos )) != -1 && iStr < 7 ){
if( iNext == iPos ){
object[iStr++] = "NA";
} else {
object[iStr++] = x.substring( iPos, iNext );
}
iPos = iNext + 1;
}
// add more "NA" if rows can have less than 7 cells
Run Code Online (Sandbox Code Playgroud)
将时间缩短到1.983秒.这比原始代码快30倍,原始代码无论如何都会遇到OutOfMemory.
只需使用uniVocity-parsers的CSV解析器,而不是尝试构建自定义解析器.您的实现可能不会快速或灵活,无法处理所有极端情况.
它具有极高的内存效率,您可以在不到一秒的时间内解析一百万行.此链接具有许多java CSV库和univocity-parsers的性能比较.
这是一个如何使用它的简单示例:
CsvParserSettings settings = new CsvParserSettings(); // you'll find many options here, check the tutorial.
CsvParser parser = new CsvParser(settings);
// parses all rows in one go (you should probably use a RowProcessor or iterate row by row if there are many rows)
List<String[]> allRows = parser.parseAll(new File("/path/to/your.csv"));
Run Code Online (Sandbox Code Playgroud)
但是,它将所有内容加载到内存中.要流式传输所有行,您可以执行以下操作:
String[] row;
parser.beginParsing(csvFile)
while ((row = parser.parseNext()) != null) {
//process row here.
}
Run Code Online (Sandbox Code Playgroud)
更快的方法是使用RowProcessor,它还提供了更大的灵活性:
settings.setRowProcessor(myChosenRowProcessor);
CsvParser parser = new CsvParser(settings);
parser.parse(csvFile);
Run Code Online (Sandbox Code Playgroud)
最后,它有内置例程,使用解析器执行一些常见任务(迭代java bean,dump ResultSets等)
这应该涵盖基础知识,检查文档以找到适合您案例的最佳方法.
披露:我是这个图书馆的作者.它是开源和免费的(Apache V2.0许可证).
| 归档时间: |
|
| 查看次数: |
17672 次 |
| 最近记录: |