Как проверить заголовки CSV с помощью процедур Univocity?

Я использую парсер Univocity CSV с подпрограммами, когда перебираю Java-бины. Есть ли способ проверить заголовок CSV? Когда я редактирую CSV и добавляю неверный заголовок, он просто вставляется в данный bean-компонент null без каких-либо ошибок.

Класс модели:

public class Customer {

@Format(formats ="yyyy-MM-dd")
@Parsed(field="C_DAY")
private Date day;

@Parsed(field="C_ID")
private Long id;

@Parsed(field="C_TYPE")
private String type;

@Format(formats ="yyyy-MM-dd")
@Parsed(field="C_ORIGIN_DATE")
private Date originDate;

@Format(formats ="yyyy-MM-dd")
@Parsed(field="C_REL_DATE")
private Date relDate;

@Parsed(field="C_LEGAL_ID")
private String legalId;

@Parsed(field="C_NAME")
private String name;}

Парсер:

    @Autowired
private CustomerDAO dao;

public void parse(File file) throws IOException, SQLException, CustomerValidationException, ParseException {
    CsvParserSettings parserSettings = new CsvParserSettings();
    parserSettings.getFormat().setLineSeparator("\n");
    parserSettings.setHeaderExtractionEnabled(false);
    CsvRoutines routines = new CsvRoutines(parserSettings);
    List<Customer> customers = new ArrayList<>();
    java.util.Date stamp = getTimestamp(file);
    dao.checkTimestampDate(stamp);


    for (Customer customer : routines.iterate(Customer.class, file, "UTF-8")) {
        validateFileDateWithFileName(stamp, customer.getDay());
        validateCustomer(customer);
        customers.add(customer);
    }
    dao.save(customers);
}

person Michael    schedule 09.10.2018    source источник


Ответы (2)


Автор библиотеки здесь. BeanListProcessor имеет свойство strictHeaderValidationEnabled, для которого вы можете установить значение true, чтобы убедиться, что все заголовки вашего класса существуют во входных данных.

Вы просто не можете использовать CsvRoutines в этом случае, поскольку этот класс реализует удобные методы, которые используют свои собственные внутренние процессоры строк, поэтому ваши будут игнорироваться. Попробуйте этот код:

    CsvParserSettings parserSettings = new CsvParserSettings();
    parserSettings.getFormat().setLineSeparator("\n");

    final List<Customer> customers = new ArrayList<>();
    final java.util.Date stamp = getTimestamp(file);
    dao.checkTimestampDate(stamp);

    parserSettings.setProcessor(new BeanProcessor<Customer>() {
        @Override
        public void beanProcessed(Customer customer, ParsingContext context) {
            validateFileDateWithFileName(stamp, customer.getDay());
            validateCustomer(customer);
            customers.add(customer);
        }
    });

    new CsvParser(parserSettings).parse(file, "UTF-8");

    dao.save(customers);

Надеюсь это поможет.

person Jeronimo Backes    schedule 09.10.2018

На основе ответа Джеронимо Бэкеса.

Если у вас есть аннотация @Header на bean-компоненте или вы знаете точные заголовки, но все еще нуждаетесь в setHeaderExtractionEnabled(true):

public <T> List<T> parse(File file, Class<T> beanType, char delimiter, Charset charset) {
    String[] headers = beanType.getDeclaredAnnotation(Headers.class).sequence(); // or other source

    CsvParserSettings parserSettings = Csv.parseRfc4180(); // or some other
    parserSettings.detectFormatAutomatically(delimiter);
    parserSettings.setHeaderExtractionEnabled(true);

    // initialize new processor (stateful, should not be reused! See implementation of parseAll)
    BeanListProcessor<T> processor= new BeanListProcessor<>();
    processor.setStrictHeaderValidationEnabled(true);
    parserSettings.setProcessor(processor);

    CsvParser csvParser = new CsvParser(parserSettings);

    csvParser.parse(file, charset);

    // header validation
    String[] headersParsed = processor.getHeaders();
    if (!Arrays.equals(headers, headersParsed)) {
        String message = String.format("Header validation failed. Expected: %s, but was: %s",
            Arrays.toString(headers), Arrays.toString(headersParsed));
        throw new DataProcessingException(message);
    }

    return beanListProcessor.getBeans();
}
person Terran    schedule 03.11.2020