当前位置: 首页 > 面试题库 >

使用SuperCSV一次验证每个字段

权浩阔
2023-03-14
问题内容

我正在尝试使用SuperCSV将数据库中的大量行(约200万行)写入CSV文件。我需要在每个单元格编写时对其进行验证,并且内置的CellProcessor表现得非常好。我想捕获CellProcessors抛出的所有异常,以便可以返回到源数据并进行更改。

问题是,当一行中存在多个错误时(例如,第一个值超出范围,第二个值为null,但不应为空),只有第一个CellProcessor会执行,因此我只会看到一个错误。我想一次处理整个文件,并在文件末尾包含一整套异常。

我正在尝试这种方法:

for (Row row : rows) {
    try {
        csvBeanWriter.write(row, HEADER_MAPPINGS, CELL_PROCESSORS);
    } catch (SuperCsvCellProcessorException e) {
        log(e);
    }
}

我该如何实现?谢谢!

编辑:这是我写的类似于猎犬的代码,以防它对任何人有帮助:

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 ExceptionCapturingCellProcessor extends CellProcessorAdaptor {

    private final List<Exception> exceptions;

    private final CellProcessor current;

    public ExceptionCapturingCellProcessor(CellProcessor current, CellProcessor next, List<Exception> exceptions) {
        super(next);
        this.exceptions = exceptions;
        this.current = current;
    }

    @Override
    public Object execute(Object value, CsvContext context) {
        // Check input is not null
        try {
            validateInputNotNull(value, context);
        } catch (SuperCsvCellProcessorException e) {
            exceptions.add(e);
        }

        // Execute wrapped CellProcessor
        try {
            current.execute(value, context);
        } catch (SuperCsvCellProcessorException e) {
            exceptions.add(e);
        }

        return next.execute(value, context);
    }
}

问题答案:

我建议编写一个自定义CellProcessor来实现此目的。可以在每个CellProcessor链的开始处放置以下处理器-
它仅将委派给其后链接的处理器,并抑制任何单元处理异常。

package example;

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 SuppressException extends CellProcessorAdaptor {

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

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

    public Object execute(Object value, CsvContext context) {
        try {
            // attempt to execute the next processor
            return next.execute(value, context);

        } catch (SuperCsvCellProcessorException e) {
            // save the exception
            SUPPRESSED_EXCEPTIONS.add(e);

            // and suppress it (null is written as "")
            return null;
        }
    }
}

它在起作用:

package example;

import java.io.StringWriter;
import java.util.Arrays;
import java.util.List;

import org.supercsv.cellprocessor.constraint.NotNull;
import org.supercsv.cellprocessor.constraint.StrMinMax;
import org.supercsv.cellprocessor.ift.CellProcessor;
import org.supercsv.exception.SuperCsvCellProcessorException;
import org.supercsv.io.CsvBeanWriter;
import org.supercsv.io.ICsvBeanWriter;
import org.supercsv.prefs.CsvPreference;

public class TestSuppressExceptions {

    private static final CellProcessor[] PROCESSORS = {
            new SuppressException(new StrMinMax(0, 4)),
            new SuppressException(new NotNull()) };

    private static final String[] HEADER = { "name", "age" };

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

        final StringWriter stringWriter = new StringWriter();
        ICsvBeanWriter beanWriter = null;
        try {
            beanWriter = new CsvBeanWriter(stringWriter,
                    CsvPreference.STANDARD_PREFERENCE);

            beanWriter.writeHeader(HEADER);

            // set up the data
            Person valid = new Person("Rick", 43);
            Person nullAge = new Person("Lori", null);
            Person totallyInvalid = new Person("Shane", null);
            Person valid2 = new Person("Carl", 12);
            List<Person> people = Arrays.asList(valid, nullAge, totallyInvalid,
                    valid2);

            for (Person person : people) {
                beanWriter.write(person, HEADER, PROCESSORS);

                if (!SuppressException.SUPPRESSED_EXCEPTIONS.isEmpty()) {
                    System.out.println("Suppressed exceptions for row "
                                        + beanWriter.getRowNumber() + ":");
                    for (SuperCsvCellProcessorException e :
                                        SuppressException.SUPPRESSED_EXCEPTIONS) {
                        System.out.println(e);
                    }
                    // clear ready for next row
                    SuppressException.SUPPRESSED_EXCEPTIONS.clear();
                }

            }

        } finally {
            beanWriter.close();
        }

        // CSV will have empty columns for invalid data
        System.out.println(stringWriter);

    }

}

这是抑制的异常输出(第4行有两个异常,每列一个):

Suppressed exceptions for row 3:
org.supercsv.exception.SuperCsvConstraintViolationException: null value 
encountered processor=org.supercsv.cellprocessor.constraint.NotNull
context={lineNo=3, rowNo=3, columnNo=2, rowSource=[Lori, null]}
Suppressed exceptions for row 4:
org.supercsv.exception.SuperCsvConstraintViolationException: the length (5) 
of value 'Shane' does not lie between the min (0) and max (4) values (inclusive)
processor=org.supercsv.cellprocessor.constraint.StrMinMax
context={lineNo=4, rowNo=4, columnNo=2, rowSource=[Shane, null]}
org.supercsv.exception.SuperCsvConstraintViolationException: null value 
encountered processor=org.supercsv.cellprocessor.constraint.NotNull
context={lineNo=4, rowNo=4, columnNo=2, rowSource=[Shane, null]}

和CSV输出

name,age
Rick,43
Lori,
,
Carl,12

请注意无效值是如何写入的,""因为SuppressException处理器会null为这些值返回(不是因为您无效,所以您还是要使用CSV输出!)。



 类似资料:
  • 我正在使用Spring Boot 2.2.0用java bean验证框架构建一个restful服务。Hibernate-Validator在幕后使用。验证工作得很好,但在一个字段与约束不匹配后会引发异常。我想先验证所有字段,然后给消费者一个包含所有错误的响应。这可能吗?

  • 问题内容: 例, 我有 然后我输入一个空值。 它说,“不能为空,长度必须在2到35之间” 是否可以告诉spring每个字段一次验证一次? 问题答案: 是的,有可能。只需像这样创建自己的注释: 重要的部分是@ReportAsSingleViolation批注

  • 我将MVC3视图模型定义为: 使用FluentValidation(v3.3.1.0)将验证定义为: 账户验证可能被定义为: 我希望列表中的每个帐户按照留档中的描述进行验证。但是,调用不起作用,因为在使用

  • 我已经在Paypal中使用沙盒成功地实现了webhook集成。现在我想让它更安全,这样只有贝宝签名的通知才被接受。我试图使用 https://developer.paypal.com/docs/api/webhooks/v1/#verify-webhook-signature\u post 但它总是返回失败。 请求是: {"auth_algo":"SHA256with RSA","transmis

  • 我想验证字段,如果存在,将失败,如果另一个字段不存在如何做到这一点?我已经创建了自定义验证,以获得基于存储ID的记录 我有字段和,并且字段根据在最大值和最小值之间进行验证,如果我显示=且未填写字段,则验证字段将通过,并显示错误,因为我未填写我希望在执行自定义验证之前检查是否为空。。 我已经阅读了laravel文档上的所有验证方法,但仍然没有找到解决方案。怎么做?

  • 晚上好,我正在尝试在下面的场景中使用Hibernate验证器: