OPENCSV自定义逻辑在解析中



我正在使用opencsv库,因为它非常易于使用,并且我获得了所有必要的功能。但是现在,我需要使用一些自定义逻辑,除了检查正确的类型,列和其他常规内容。我有一个带有firstNamesecondNamefirstSalarylastSalary等列的CSV。我想检查firstDayOfWork在切割过程中是否小于lastDayOfWork,并在错误的过程中添加新的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

或某些自定义装饰逻辑,例如检查某些字段捕获REGEXP,同时两个字段大于0等等。

我首先可以将其转换为豆子,然后在第二个周期中检查我的bean对这些规则,但是有很多行,它将需要更长的时间,因此,我想在一个过程中检查它。

我可以通过OpenCSV获得它吗?如果是,怎么样?如果没有,我可以使用什么工具?谢谢。

基于如何通过使用opencSv?来创建有效CSV记录的列表,而不是在seters中扔一个illegalargumentException,您可以:

  1. 创建一个beanverifier来验证整个豆类之后;
  2. 在错误上投掷CsvConstraintViolationException;
  3. .withThrowExceptions(false)添加到CsvToBeanBuilder;
  4. 调用getCapturedExceptions()收集验证错误。

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

示例

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));

员工

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;
}

虽然opencsv上有一个请求/愿望列表,但我认为它不会为您提供帮助

对于您想要的东西,您应该在固定器中添加一个检查器,以便在值不好时抛出异常。这是我的豆子和测试。

public class SetterBean {
    @CsvBindByName(column = "First Name", required = true)
    private String firstName;
    @CsvBindByName(column = "Last Name", required = true)
    private String lastName;
    @CsvBindByName(column = "First Salary")
    private Long firstSalary;
    @CsvBindByName(column = "Last Salary")
    private Long lastSalary;
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
    public void setFirstSalary(Long firstSalary) {
        if (lastSalary != null && (firstSalary.compareTo(lastSalary) > 0)) {
            throw new IllegalArgumentException("First Salary cannot be greater than Last Salary.");
        }
        this.firstSalary = firstSalary;
    }
    public void setLastSalary(Long lastSalary) {
        if (firstSalary != null && (lastSalary.compareTo(firstSalary) < 0)) {
            throw new IllegalArgumentException("Last Salary cannot be less than First Salary.");
        }
        this.lastSalary = lastSalary;
    }
}
public class SetterValidationTest {
    private static final String HEADER = "First Name,Last Name,First Salary,Last Salaryn";
    CsvToBean<SetterBean> csvToBean;
    @Test
    public void normalData() {
        String data = HEADER + "First, Last, 1, 2";
        csvToBean = new CsvToBeanBuilder<SetterBean>(new StringReader(data))
                .withType(SetterBean.class)
                .build();
        List<SetterBean> beans = csvToBean.parse();
        assertEquals(1, beans.size());
    }
    @Test(expected = Exception.class)
    public void firstGTLast() {
        String data = HEADER + "First, Last, 2, 1";
        csvToBean = new CsvToBeanBuilder<SetterBean>(new StringReader(data))
                .withType(SetterBean.class)
                .build();
        List<SetterBean> beans = csvToBean.parse();
    }
}

这是结果。

Exception in thread "pool-1-thread-1" java.lang.RuntimeException: com.opencsv.exceptions.CsvDataTypeMismatchException
    at com.opencsv.bean.concurrent.ProcessCsvLine.run(ProcessCsvLine.java:91)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
    at java.lang.Thread.run(Thread.java:722)
Caused by: com.opencsv.exceptions.CsvDataTypeMismatchException
    at com.opencsv.bean.AbstractBeanField.assignValueToField(AbstractBeanField.java:192)
    at com.opencsv.bean.AbstractBeanField.setFieldValue(AbstractBeanField.java:159)
    at com.opencsv.bean.concurrent.ProcessCsvLine.processField(ProcessCsvLine.java:140)
    at com.opencsv.bean.concurrent.ProcessCsvLine.processLine(ProcessCsvLine.java:126)
    at com.opencsv.bean.concurrent.ProcessCsvLine.run(ProcessCsvLine.java:82)
    ... 3 more
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at com.opencsv.bean.AbstractBeanField.assignValueToField(AbstractBeanField.java:187)
    ... 7 more
Caused by: java.lang.IllegalArgumentException: Last Salary cannot be less than First Salary.
    at integrationTest.BeanTests.SetterBean.setLastSalary(SetterBean.java:33)
    ... 12 more

希望有帮助。

Scott Conway:(

相关内容

  • 没有找到相关文章

最新更新