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

Sag*_*gar 5 java csv parsing iterator

在我的 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...)
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我使用.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
Run Code Online (Sandbox Code Playgroud)

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

根据我的理解 iterator.hasNext() 尝试通过将 csv 记录列映射到 POJO 字段来检查下一个元素是否存在,并且由于 csv 记录标题中的无效数据计数与记录文件不匹配,因此出现错误 java.lang.RuntimeException: com.opencsv.exceptions.CsvRequiredFieldEmptyException: Number of data fields does not match number of headers.

编辑

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
Run Code Online (Sandbox Code Playgroud)

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

Ole*_*ndr 11

  1. 添加CsvToBeanBuilder .withThrowExceptions(false)到忽略运行时异常
  2. 解析豆子
  3. 调用getCapturedExceptions()以获取在导入期间会抛出但被抑制的所有异常
  4. 遍历CsvException数组(解析后)并记录异常

请参阅下面的代码片段:

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
    });
Run Code Online (Sandbox Code Playgroud)