java - 使用 CSV 解析器根据多个约束验证每个归档

标签 java csv supercsv

我正在处理一个需求,我需要根据多个验证来解析 CSV 记录字段。我正在使用 supercsv,它支持现场级处理器来验证数据。

我的要求是根据多次验证来验证每个记录/行字段,并将它们以成功/失败状态保存到数据库中。对于失败记录,我必须使用一些代码显示所有失败的验证。

super CSV 是工作文件,但它仅检查某个字段的第一次验证,如果失败,则忽略同一字段的第二次验证。请查看下面的代码并帮助我解决此问题。

package com.demo.supercsv;

import java.io.FileReader;
import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;

import org.supercsv.cellprocessor.Optional;
import org.supercsv.cellprocessor.constraint.NotNull;
import org.supercsv.cellprocessor.constraint.StrMinMax;
import org.supercsv.cellprocessor.constraint.StrRegEx;
import org.supercsv.cellprocessor.constraint.UniqueHashCode;
import org.supercsv.cellprocessor.ift.CellProcessor;
import org.supercsv.exception.SuperCsvCellProcessorException;
import org.supercsv.io.CsvBeanReader;
import org.supercsv.io.CsvBeanWriter;
import org.supercsv.io.ICsvBeanReader;
import org.supercsv.io.ICsvBeanWriter;
import org.supercsv.prefs.CsvPreference;

public class ParserDemo {

    public static void main(String[] args) throws IOException {

        List<Employee> emps = readCSVToBean();
        System.out.println(emps);
        System.out.println("******");
        writeCSVData(emps);
    }

    private static void writeCSVData(List<Employee> emps) throws IOException {
        ICsvBeanWriter beanWriter = null;
        StringWriter writer = new StringWriter();
        try{
            beanWriter = new CsvBeanWriter(writer, CsvPreference.STANDARD_PREFERENCE);
            final String[] header = new String[]{"id","name","role","salary"};
            final CellProcessor[] processors = getProcessors();

            // write the header
            beanWriter.writeHeader(header);

            //write the beans data
            for(Employee emp : emps){
                beanWriter.write(emp, header, processors);
            }
        }finally{
            if( beanWriter != null ) {
                beanWriter.close();
            }
        }
        System.out.println("CSV Data\n"+writer.toString());
    }

    private static List<Employee> readCSVToBean() throws IOException {
        ICsvBeanReader beanReader = null;
        List<Employee> emps = new ArrayList<Employee>();
        try {
            beanReader = new CsvBeanReader(new FileReader("src/employees.csv"),
                    CsvPreference.STANDARD_PREFERENCE);

            // the name mapping provide the basis for bean setters 
            final String[] nameMapping = new String[]{"id","name","role","salary"};
            //just read the header, so that it don't get mapped to Employee object
            final String[] header = beanReader.getHeader(true);
            final CellProcessor[] processors = getProcessors();

            Employee emp;

            while ((emp = beanReader.read(Employee.class, nameMapping,
                    processors)) != null) {
                emps.add(emp);


                if (!CaptureExceptions.SUPPRESSED_EXCEPTIONS.isEmpty()) {
                    System.out.println("Suppressed exceptions for row "
                                        + beanReader.getRowNumber() + ":");
                    for (SuperCsvCellProcessorException e :
                        CaptureExceptions.SUPPRESSED_EXCEPTIONS) {
                        System.out.println(e);
                    }
                    // for processing next row clearing validation list
                    CaptureExceptions.SUPPRESSED_EXCEPTIONS.clear();
                }

            }

        } finally {
            if (beanReader != null) {
                beanReader.close();
            }
        }
        return emps;
    }

    private static CellProcessor[] getProcessors() {

        final CellProcessor[] processors = new CellProcessor[] { 

                new CaptureExceptions(new NotNull(new StrRegEx("\\d+",new StrMinMax(0, 2)))),//id must be in digits and should not be more than two charecters
                new CaptureExceptions(new Optional()), 
                new CaptureExceptions(new Optional()), 
                new CaptureExceptions(new NotNull()), 
                 // Salary
        };
        return processors;
    }

}

异常处理程序:

package com.demo.supercsv;

import java.util.ArrayList;
import java.util.List;
import org.supercsv.cellprocessor.CellProcessorAdaptor;
import org.supercsv.cellprocessor.ift.CellProcessor;
import org.supercsv.exception.SuperCsvCellProcessorException;
import org.supercsv.util.CsvContext;

public class CaptureExceptions extends CellProcessorAdaptor {

    public static List<SuperCsvCellProcessorException> SUPPRESSED_EXCEPTIONS = 
            new ArrayList<SuperCsvCellProcessorException>();

    public CaptureExceptions(CellProcessor next) {
        super(next);
    }

    public Object execute(Object value, CsvContext context) {
        try {
            return next.execute(value, context);

        } catch (SuperCsvCellProcessorException e) {
            // save the exception
            SUPPRESSED_EXCEPTIONS.add(e);
            if(value!=null)
                return value.toString();
                else
                    return "";
        }
    }
}

示例 csv 文件

ID,Name,Role,Salary
a123,kiran,CEO,"5000USD"
2,Kumar,Manager,2000USD
3,David,developer,1000USD

当我运行程序 supercsv 异常处理程序时,第一行中的 ID 值显示此消息

Suppressed exceptions for row 2:
org.supercsv.exception.SuperCsvConstraintViolationException: 'a123' does not match the regular expression '\d+'
processor=org.supercsv.cellprocessor.constraint.StrRegEx
context={lineNo=2, rowNo=2, columnNo=1, rowSource=[a123, kiran, CEO, 5000USD]}
[com.demo.supercsv.Employee@23bf011e, com.demo.supercsv.Employee@50e26ae7, com.demo.supercsv.Employee@40d88d2d]

对于字段 Id 长度不应为空且超过 2,并且它应该是数字...我已经像这样定义了字段处理器。

new CaptureExceptions(new NotNull(new StrRegEx("\\d+",new StrMinMax(0, 2))))

但是如果给定的输入不是数字, super csv 会忽略第二次验证(最大长度 2)...如果我的输入是 100,则其验证最大长度...但是如何对错误的输入进行两次验证。请帮助我

最佳答案

SuperCSV 单元处理器将按顺序工作。因此,如果它通过了前一个约束验证,那么它将检查下一个。

为了实现你的目标,你需要编写一个自定义的 CellProcessor,它将检查输入是否是数字(数字)并且长度是否在 0 到 2 之间。 因此,这两项检查都是在一个步骤中完成的。

关于java - 使用 CSV 解析器根据多个约束验证每个归档,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34379418/

相关文章:

适用于 Java1.2 或 Java1.5 的 Java-mongodb 驱动程序

java - maven可以同时使用本地和远程仓库吗?

Java, Spring : Setting timeout for a method so the code returns to method end.

java - 从另一只耳朵访问耳朵里的 jar 里的类

java - 忽略 csv 中的额外列 - SuperCSV

python - 将数据框作为 csv 文件从 google colab 导出到 google drive

c# - Microsoft ACE OLEDB 12.0 - 无 header .CSV 的 F1 语法导致异常

python - 使用子进程python时无法访问文件的内容

java - NoSuchMethodException : java. time.LocalDateTime.<init>() 使用 Super CSV 读取 CSV