parcing

时间:2018-02-08 17:13:51

标签: java csv opencsv

我正在使用openCsv库,因为它非常易于使用,而且我得到了所有必要的功能。但是现在我需要使用一些自定义逻辑,除了检查正确的类型,列和其他常见的东西。我有一个包含firstNamesecondNamefirstSalarylastSalary列等的csv。我想在parcing过程中检查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等等。

我可以先将parce转换为bean并将其转换为bean,然后通过第二次循环检查我的bean以查看这些规则,但是可能会有很多行并且需要更长的时间,因此,我想在一个进程中检查它

我可以通过openCsv获取它吗?如果是,怎么样?如果不是,我可以使用哪种工具? 谢谢。

2 个答案:

答案 0 :(得分:0)

虽然todo/wish list上有关于OpenCSV的请求,但我认为它不会对您有所帮助,因为它有关于预解析验证的信息

对于你想要的东西,你应该在你的setter中添加一个检查,以便在值不好时抛出异常。这是我的Bean和测试。

_config.yml

这是结果。

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 Salary\n";

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

希望有所帮助。

斯科特康威:)

答案 1 :(得分:0)

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

  1. 创建一个 BeanVerifier 以在创建后验证整个 bean;
  2. 出错时抛出 [Route("Reservations")] public ActionResult Index() { MTAPI mTAPI = new MTAPI(); mTAPI.VeriAl(); reservations.EditPassedTourTime(); reservation.Raccount = reservations.GetAllResAccountLMTD(); return View(reservation); } public void VeriAl() { int VoucherId = rservations.GetLastVoucher().fldId; using (example _db= new example()) { var newdata =_db.Voucher(); newdata.beforerecordId = VoucherId; _db.Voucher.Add(newdata); _db.SaveChanges(); } }
  3. CsvConstraintViolationException 添加到 .withThrowExceptions(false);
  4. 调用 CsvToBeanBuilder 以收集验证错误。

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

示例

getCapturedExceptions()

EmployeeBean

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

BeanVerifier

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
}