多年来我一直在使用以下逻辑解析我的夜间批处理作业中的csv文件而没有问题。无论如何我正在完全重写应用程序,我现在想知道使用opencsv这样的东西是否可能有任何性能/质量提升?我没有其他图书馆的经验,所以我希望有经验的其他人可以参与其中。
while ((line = br.readLine()) != null) {
String[] items = line.split(",");
for (int i = 0; i < items.length; ++i) {
// Remove extra quote
if (items[i].length > 2) {
items[i] = items[i].replaceAll("\"", "");
}
// Replace blank items with nulls
if (items[i].matches("^\\s*$")) {
items[i] = null;
}
}
String item0 = item[0];
String item1 = item[1];
}
答案 0 :(得分:4)
chrylis 给出的答案是正确的,您可能无法获得性能但是opencsv会为您处理所有情况。
但如果你真的担心性能,那么你的代码中的一些调整可以帮助你提高性能,
在分析String.Split的代码之后
public String[] split(String regex) {
return split(regex, 0);
}
public String[] split(String regex, int limit) {
return Pattern.compile(regex).split(this, limit);
}
对于每个String,编译一个新Pattern,Pattern.compile的代码是
public static Pattern compile(String regex, int flags) {
return new Pattern(regex, flags);
}
上面再次重复创建Pattern对象的代码,
items[i].matches("^\\s*$")
因此,如果您的文件有数百万行,那么创建数百万个Pattern对象可能会产生开销,因此您可以将代码更改为,
Pattern pat = Pattern.compile(",");
Pattern regexPattern = Pattern.compile("^\\s*$");
while ((line = br.readLine()) != null)
{
String[] items = pat.split(line, 0);
for (int i = 0; i < items.length; ++i)
{
if (items[i] != null && items.length > 2) // I think it should be items[i].length() > 2
{ //We can also remove this null check as splitted strings will never be null
items[i] = items[i].replaceAll("\"", "");
}
if (regexPattern.matcher(items[i]) .matches()) {
items[i] = null;
}
}
}
性能增益在小文件中不可见,但对于大文件,如果相同的代码执行数百万个文件,您将看到显着的性能提升。
答案 1 :(得分:3)
您将无法获得任何性能,但是库将帮助您处理具有嵌入式逗号的字段。微软使用双引号而不是逃避逗号的令人讨厌的解决方案是手工处理的痛苦,opencsv将为您处理所有这些。
答案 2 :(得分:0)
要添加选项,请考虑Jackson CsvMapper。
我使用macbook pro上的jackson CsvMapper在12分钟内从大约4k个文件中解析了3600万行。这是用它来直接映射到某些地方的POJO,并使用它在其他地方每行读取Object []并应用大量辅助处理来规范化输入。
它也很容易使用:
as Object []
CsvMapper mapper = new CsvMapper();
mapper.enable(CsvParser.Feature.WRAP_AS_ARRAY);
File csvFile = new File("input.csv"); // or from String, URL etc
MappingIterator<Object[]> it = mapper.reader(Object[].class).readValues(csvFile);
作为POJO
public class CSVPerson{
public String firstname;
public String lastname;
//etc
}
CsvMapper mapper = new CsvMapper();
CsvSchema schema = CsvSchema.emptySchema().withHeader().withColumnSeparator(delimiter);
MappingIterator<CSVPerson> it = = mapper.reader(CSVPerson).with(schema).readValues(input);
while (it.hasNext()){
CSVPerson row = it.next();
}
我总是赞美这个图书馆,这很棒。它也非常灵活。