java - Opencsv解析中的自定义逻辑

标签 java csv opencsv

我正在使用 openCsv 库,因为它非常易于使用,并且我获得了所有必要的功能。但现在我需要使用一些自定义逻辑,除了检查正确的类型、列和其他常见的东西。我有一个 csv,其中包含 firstNamesecondNamefirstSalarylastSalary 等列。我想在解析过程中检查 firstDayOfWork 是否小于 lastDayOfWork ,如果为 false,则添加一个新的 csvException 。所以,如果现在我正在解析文件

firstName,secondName,firstSalary,lastSalary
John, Doe, testtext, 5000
Alice, , 100, 5000
Harry, Smith, 400, 200

并处理 csvExcpetions 列表,我可以获得像

这样的解析结果
Number of mistakes: 2
Line 1: Conversion of testtext to java.lang.Integer failed.
Line 2: Field 'secondName' is mandatory but no value was provided.

我想要类似的东西

Number of mistakes: 3
Line 1: Conversion of testtext to java.lang.Integer failed.
Line 2: Field 'secondName' is mandatory but no value was provided.
Line 3: firstSalary cannot be more than lastSalary

或者一些自定义解析逻辑,例如检查某个字段是否捕获正则表达式、两个字段同时大于 0 等。

我可以首先将其解析并转换为bean,然后在第二个周期检查我的bean是否符合这些规则,但是可能会有很多行,并且需要更长的时间,所以,我想在一个过程中检查它。

我可以通过openCsv获取它吗?如果是的话,怎么办?如果不是,我还可以使用什么其他工具? 谢谢。

最佳答案

基于How to create a list of valid CSV records by logging the error of invalid record using OpenCsv? ,您可以:

,而不是在 setter 中抛出 IllegalArgumentException
  1. 创建一个 BeanVerifier 以在创建后验证整个 bean;
  2. 出错时抛出 CsvConstraintViolationException
  3. .withThrowExceptions(false)添加到CsvToBeanBuilder
  4. 调用 getCapturedExceptions() 来收集验证错误。

此解决方案的优点是您可以根据需要收集 CSV 异常(exception)列表:

示例

final CsvToBean<EmployeeBean> csvToBean = 
    new CsvToBeanBuilder<EmployeeBean>(new FileReader("c:\\test.csv"))
        .withType(EmployeeBean.class)
        .withVerifier(new EmployeeSalaryVerifier())
        .withThrowExceptions(false)
        .build();

final List<EmployeeBeans> employees = csvToBean.parse();
List<CsvException> exceptions = parser.getCapturedExceptions();

// logging number of mistakes and, for each exception, its line number and message
logger.error("Number of Mistakes: {}", exceptions.size());
employees.getCapturedExceptions().stream().forEach(ex ->
    logger.error("Line {}: {}", ex.getLineNumber(), ex.getMessage(), ex));

EmployeeBean

public class EmployeeBean {

    @CsvBindByName(column = "First Name", required = true)
    private String firstName;
    @CsvBindByName(column = "Last Name", required = true)
    private String lastName;
    @CsvBindByName(column = "First Salary" required = true)
    private Long firstSalary;
    @CsvBindByName(column = "Last Salary")
    private Long lastSalary;

    // regular getters and setters, no validation here
}

BeanVerifier

public class EmployeeSalaryVerifier implements BeanVerifier<EmployeeBean> {

    @Override
    public boolean verifyBean(Employee bean) throws CsvConstraintViolationException {
    // check salary
    if (bean.getLastSalary() != null && bean.getFirstSalary().compareTo(bean.getLastSalary()) > 0) {
        throw new CsvConstraintViolationException("First Salary cannot be greater than Last Salary.");
    }

    return true;
}

关于java - Opencsv解析中的自定义逻辑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48691164/

相关文章:

java - 就餐哲学家java替代解决方案

java - Hibernate 不从连接池中释放连接

unit-testing - Spock:从 CSV 文件读取测试数据

java - 使用 openCSV 导出数据时是否可以删除分隔符?

java - 频繁调用 java.lang.Runtime 的totalMemory()/freeMemory() 对性能有何影响?

java - 如何在类内部执行从类内部适配器访问的内部类

python - 查询维护外键关系的CSV文件?这可能吗?

csv - 如何在 WSO2 Micro Integrator 中跳过 CSV 文件中的标题

python - 从 csv 文件中读取列并使用 pandas 将它们放入新的 csv 文件中

java - OpenCSV + JMS/MDB 行为 + 性能问题