【问题标题】:How to create a list of valid CSV records by logging the error of invalid record using OpenCsv?如何通过使用 OpenCsv 记录无效记录的错误来创建有效 CSV 记录的列表?
【发布时间】:2019-11-11 19:21:12
【问题描述】:

在我的 CSV 中,我的数据不一致,因此我必须在迭代记录时记录错误,并希望创建有效 CSV 记录的 POJO 列表。我正在使用 OpenCsv 来处理 CSV 文件。 如果有任何错误,我已经添加了 try-catch 块来记录错误,但在 while(iterator.hasNext()) 存在异常/错误,因为下一条记录有一些格式不正确的数据。

那么如何记录错误并继续处理下一条记录呢?

List<UserProvisioning> list = new ArrayList<>();
CsvToBean<UserProvisioning> beans = new CsvToBeanBuilder<UserProvisioning>(
        new FileReader(file.getAbsolutePath())).withType(UserProvisioning.class)
                .withIgnoreQuotations(true).build();
Iterator<UserProvisioning> iterator = beans.iterator();
while (iterator.hasNext()) {
    try {
        UserProvisioning userProvisioning = (UserProvisioning) iterator.next();
        System.out.println(userProvisioning.getFIRST_NAME());
        list.add(userProvisioning);
    } catch (Exception e) {
        // TODO Auto-generated catch block
        logger.error("Error occured...)
    }
}

如果我使用 .withThrowExceptions(false),我可以处理所有有效记录,但无法记录错误。

错误

java.lang.RuntimeException: com.opencsv.exceptions.CsvRequiredFieldEmptyException: Number of data fields does not match number of headers.
    at com.opencsv.bean.concurrent.ProcessCsvLine.run(ProcessCsvLine.java:101)
    at com.opencsv.bean.CsvToBean$CsvToBeanIterator.readLineWithPossibleError(CsvToBean.java:551)
    at com.opencsv.bean.CsvToBean$CsvToBeanIterator.readSingleLine(CsvToBean.java:571)
    at com.opencsv.bean.CsvToBean$CsvToBeanIterator.next(CsvToBean.java:591)
    at com.apds.partner.nycdoc.main.NycDocApplication.main(NycDocApplication.java:90)
    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)
    ... 9 more

如何通过使用 OpenCsv 记录无效记录的错误来创建有效 csv 记录的列表?

根据我的理解 iterator.hasNext() 尝试通过将 csv 记录列映射到 POJO 字段来检查下一个元素是否存在,并且由于 csv 记录标题中的数据无效,因此计数与记录文件不匹配,因此错误 @987654323 @

编辑

OpenCSV 4.6 版

样本记录:

ID1,ID2,FIRST_NAME,LAST_NAME,BIRTH_DATE,HA1,HA2,TYPE,STATUS,DT,LEVEL
3491905454,04572538R,L,L,1964-08-01,RNDC,M4SL,GP  ,DEP,,
3491901894,04353902J,TO,TO,1962-10-20,AMKC,QUAD-L3,GP  ,DE,,
3491903493,01940960Y,JAM"ES,TO,1985-03-12,GRVC,13A,PS  ,DPV,,
8951900652,08661334Z,"ROT,TEST",RODRIGUEZ,1971-09-17,AMKC,1 TOP,GP  ,DE,,
4411801431,02661015Y,CET,TEC,1964-06-21,RNDC,M4NU,GP  ,DE,,
9801900155,06467584H,RAT,BAT,1969-12-01,GRVC,8A,GP  ,DE,,GSL3

第 4 行和第 5 行数据不一致

【问题讨论】:

  • 尝试在while (iterator.hasNext())@Sagar周围包裹另一个try catch块
  • @hydroPenguin 然后它会再次记录该行的错误并停止迭代循环
  • 这是一种有趣的行为。假设hasNext() 不应该抛出任何异常,并且抛出的所有异常都通过以下try catch 块处理,您只记录它而不抛出它。最好的办法是使用我刚才建议并由另一个答案 getCapturedExceptios() 发布的方法。

标签: java csv parsing iterator


【解决方案1】:
  1. 添加到CsvToBeanBuilder .withThrowExceptions(false) 到 忽略运行时异常
  2. 解析 bean
  3. 调用getCapturedExceptions() 以获取所有异常 会在导入期间被抛出,但被抑制
  4. 遍历CsvException数组(解析后)并记录 例外情况

见下面的代码sn-p:

final CsvToBean<UserProvisioning> beans = 
    new CsvToBeanBuilder<UserProvisioning>(new FileReader("c:\\test.csv"))
        .withType(UserProvisioning.class)
        .withIgnoreQuotations(true)
        .withThrowExceptions(false) //1
        .build();

    final List<UserProvisioning> users = beans.parse();//2
    users.stream().forEach((user) -> {
        logger.info("Parsed data:" + user.toString());
    });

    beans.getCapturedExceptions().stream().forEach((exception) -> { //3
        logger.error("Inconsistent data:" + 
                      String.join("", exception.getLine()), exception);//4
    });

【讨论】:

    【解决方案2】:

    在我看来错误是由CsvToBean&lt;UserProvisioning&gt; beans = ... 引发的

    快速阅读this,我认为这可能是由于您在 CSV 文件中的标题中的一些错误造成的。

    【讨论】:

    • 没有。错误发生在 while(iterator.hasNext())。我确实调试了程序
    • em.. 那么它可能是不符合标头的记录之一?您的代码似乎对于处理异常是正确的,它不应该抛出它,因为您只记录它。你的logger 在其他地方工作正常吗?
    • 我刚刚发现有一种方法可以获取异常。基本上你做withThrowExceptions(false);通过在beans 上调用getCapturedExceptions() 声明异常列表(详情here。)当您遍历beans 时,检查列表是否为空,如果不是则表示发生了异常,此时记录它,并删除记录的异常。
    • 我必须记录无效记录的错误。使用 withThrowExceptions(false) 它不会抛出异常。
    • 好吧,那么这个方法行不通。你的logger 在其他地方也能正常工作吗?您使用的是什么日志记录框架? log4j?
    猜你喜欢
    • 2014-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-16
    • 2020-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多