Java Opencsv解析csv文件,包含“名字中有双引号”和“双引号括起来的名字中含有逗号”的列。

3
我有以下数据:
ID1,ID2,FIRST_NAME,LAST_NAME,BIRTH_DATE,HA1,HA2,HA3,STATUS,DT
99,13863926H,MAL"COLMHS,ABBOT,1997-04-09,AMKC,RR,RR  ,DE,
89,12973388H,"SAGAR,TARLE",ABDAT,1997-11-02,RNDC,RR,RR  ,DE,
71,88JunkTest,Howdy,Doody,1985-11-02,RNDC,HA,HACLASSTYPE  ,DE,2019-12-25

我正在尝试使用OpenCSV解析CSV文件,其中我的CSV文件的第一个名字可能包含双引号(MAL"COLMHS)或带逗号的双引号("SAGAR,TARLE"),或者没有双引号的名字。
使用.withIgnoreQuotations(true)可以解析第一行(MAL"COLMHS),但无法解决解析第二行的问题。
我尝试了多个StackOverflow链接提供的解决方案,但都无法解决问题。
我知道我的CSV文件不一致,但客户的CSV文件中有太多这样的记录,手动使其一致很困难,因此正在尝试寻找自动化解决方案。
 List<Results> beans = new CsvToBeanBuilder<Results>(new FileReader(file.getAbsolutePath()))
                            .withType(Results.class)
                            .withIgnoreQuotations(true)
                            .build().parse();

错误

java.lang.RuntimeException: Error parsing CSV line: 3. [3491903139,12973388H,SAGAR,TARLE,ABDAT,1997-11-02,RNDC,RR,RR  ,DE,]
    at com.opencsv.bean.CsvToBean.parse(CsvToBean.java:366)
    at com.apds.partner.nycdoc.main.NycDocApplication.main(NycDocApplication.java:81)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: com.opencsv.exceptions.CsvRequiredFieldEmptyException: Number of data fields does not match number of headers.
    at com.opencsv.bean.HeaderColumnNameMappingStrategy.verifyLineLength(HeaderColumnNameMappingStrategy.java:110)
    at com.opencsv.bean.AbstractMappingStrategy.populateNewBean(AbstractMappingStrategy.java:313)
    at com.opencsv.bean.concurrent.ProcessCsvLine.processLine(ProcessCsvLine.java:132)
    at com.opencsv.bean.concurrent.ProcessCsvLine.run(ProcessCsvLine.java:85)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
*****

编辑: 我也尝试使用SuperCSV,但问题依旧。


你应该发布你尝试过的代码,这样我们才能知道哪里出了问题。 - Sterconium
请检查更新后的代码。 - stackUser
那么"SAGAR,TARLE"会被解析为FIRST_NAME,其值为SAGAR,TARLE吗?请让我知道我的理解是否正确。 - hagarwal
可能这篇文章 https://dev59.com/DZ7ha4cB1Zd3GeqPnLE0 可以帮到你。祝好运! - Dmitriy S
顺便说一句,最好的解决方案是要求客户提供格式良好的CSV文件。这样你在处理这个文件时就会少一个问题,客户也会少一个bug,全球技术债务总量也会减少一点。 :D - Xobotun
显示剩余2条评论
2个回答

0

你的 CSV 文件格式错误。根据 RFC-4180,第2.5节

如果字段未用双引号括起来,则字段内不能出现双引号。

和第2.7节

如果使用双引号括起字段,则在字段内出现的双引号必须通过在其前面添加另一个双引号进行转义。

我查看了这个问题, 尝试用双倍的双引号替换所有单引号。不要忘记将所有字段都用双引号括起来。

在你的例子中,99,13863926H,"MAL""COLMHS",ABBOT,1997-04-09,AMKC,RR,RR ,DE, 应该可行。

更新:如果您不想手动编辑以使其符合RFC标准,我建议您运行此正则表达式^(?:\d*,[^,]*,)([^"]\w+(?:"\w+)+)(?:,)来检查有多少个错误记录。

您可以使用唯一的捕获组提取格式不正确的名称并正确转义它,然后将更改写回文件并使用您选择的解析器重新读取它。


0

我认为这里的真正问题是你的CSV文件不符合规范。

第一行数据有10个字段,其中一个包含了一个不平衡的双引号。

  • 如果你不忽略双引号,那么第一行数据就无法解析。

  • 如果你忽略双引号,那么第二行数据就有11个字段。

基本上,第一行是格式错误的。它应该是这样的:

 99,13863926H,"MAL""COLMHS",ABBOT,1997-04-09,AMKC,RR,RR  ,DE,

我认为除了拒绝这个畸形输入,没有好的解决方法:

  • 如果问题在于坏数据,请让人工修复(手动创建的)输入文件或从中提取输入文件的数据源。

  • 如果问题出现在提取数据并生成CSV的程序中,则需要修复该程序

如果您真的想按原样解析此输入,则需要手动实现自己的CSV解析器来完成任务。 OpenCSV无法处理此输入,任何其他基于标准的解析器也无法处理。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接