我试图解析一个几乎有效的csv文件,其中包含99.9%正确和有效的数据。然而,中途有一些记录是无效的(引用太多)。
a,b,"c",d
a,b,""c""",d
我的代码
try (Reader reader = new BufferedReader(new FileReader(file), BUFFERED_READER_SIZE);
CSVParser csvParser = new CSVParser(reader, CSVFormat.EXCEL)
) {
Iterator<CSVRecord> iterator = csvParser.iterator();
CSVRecord record;
while (iterator.hasNext()) {
try {
record = iterator.next();
} catch (IllegalStateException e) {
}
}
} catch (IOException e) {
}
如何解析csv,使它在遇到无效行/记录时跳过它并移到下一行?
1条答案
按热度按时间jei2mxaa1#
我觉得你没办法解决这个问题。
CSVParser
是最后一个类,不允许控制它解析底层流的方式。但是,有一个自定义迭代器可以解决这个问题。然而,我认为这无论如何都不是一个好主意:
它不能返回
CSVParser
示例。它可能会返回一个
Iterator<CSVRecord>
而不是Stream<CSVRecord>
(除此之外filter
但是我发现流更容易实现。它为每一行创建一个新的csv解析器,因此这个方法为包含“太多”行的csv文档创建许多对象。字符串读取器可能是可重用的。
该方法的整体思想是,它不是一个csv解析器,它假设每一行只包含一行(我真的不记得csv/tsv是否允许多行记录),因此它仅仅通过设计就违反了csv解析规则。它还不支持头文件(但是可以很容易地改进)。
如果可能的话,请让您的csv解析器使用有效的csv文档,而不使用像这样的解决方法。
编辑1
上面的代码中存在一个实现缺陷:流返回的所有记录现在都具有
recordNumber
设置为1
.现在我相信这个请求不能用apachecommons csv解析器修复,因为
CSVRecord
构造函数也是包私有的,如果不使用反射或入侵其声明包,则不能在包外部示例化。抱歉,你要么修复了你的csv文件,要么使用另一个解析器,可以解析“更宽松”。