Как читать плоский заголовок файла и тело отдельно в Spring Batch

Я делаю простую пакетную работу с Spring Batch и Spring Boot.

Мне нужно прочитать плоский файл, отделить данные заголовка (первая строка) от данных тела (остальные строки) для обработки отдельной бизнес-логики, а затем записать все в один файл.

Как вы можете видеть, заголовок имеет 5 параметров, которые должны быть сопоставлены одному классу, а тело имеет 12, которые должны быть сопоставлены другому.

Сначала я подумал об использовании FlatFileItemReader и пропустил заголовок. Затем используйте skippedLinesCallback для обработки этой строки, но я не мог понять, как это сделать.

Я новичок в Spring Batch и Java Config. Если кто-то может помочь мне написать решение для моей проблемы, я бы действительно его оценил!

Я оставляю здесь входной файл:

01.01.2017|SUBDCOBR|12:21:23|01/12/2016|31/12/2016
01.01.2017|12345678231234|0002342434|BORGIA RUBEN|27-32548987-9|FA|A|2062-
00010443/444/445|142,12|30/08/2017|142,01
01.01.2017|12345673201234|2342434|ALVAREZ ESTHER|27-32533987-9|FA|A|2062-
00010443/444/445|142,12|30/08/2017|142,02
01.01.2017|12345673201234|0002342434|LOPEZ LUCRECIA|27-32553387-9|FA|A|2062-
00010443/444/445|142,12|30/08/2017|142,12
01.01.2017|12345672301234|0002342434|SILVA JESUS|27-32558657-9|NC|A|2062-
00010443|142,12|30/08/2017|142,12

Ура!

РЕДАКТИРОВАТЬ 1: Это было бы мое первое посещение. Мой POJO "тела" называется DetalleFacturacion, а мой POJO "заголовка" - CabeceraFacturacion. Читатель, я подумал сделать это с помощью DetalleFacturacion pojo, поэтому я могу пропустить заголовок и обработать его позже... однако я не уверен, как назначить данные заголовка в CabeceraFacturacion.

public FlatFileItemReader<DetalleFacturacion> readerDetalleFacturacion(){

    FlatFileItemReader<DetalleFacturacion> reader = new FlatFileItemReader<>();

    reader.setLinesToSkip(1);
    reader.setResource(new ClassPathResource("/inputFiles/GLEO-MN170100-PROCESO01-SUBDFACT-000001.txt"));

    DefaultLineMapper<DetalleFacturacion> detalleLineMapper = new DefaultLineMapper<>();

    DelimitedLineTokenizer tokenizerDet = new DelimitedLineTokenizer("|");
    tokenizerDet.setNames(new String[] {"fechaEmision", "tipoDocumento", "letra", "nroComprobante",  
                                "nroCliente", "razonSocial", "cuit", "montoNetoGP", "montoNetoG3",
                                "montoExento", "impuestos", "montoTotal"});

    LineCallbackHandler skippedLineCallback = new LineCallbackHandler() {

        @Override
        public void handleLine(String line) {

            String[] headerSeparado = line.split("|");

            String printDate = headerSeparado[0];
            String reportIdentifier = headerSeparado[1];
            String tituloReporte = headerSeparado[2];
            String fechaDesde = headerSeparado[3];
            String fechaHasta = headerSeparado[4];

            CabeceraFacturacion cabeceraFacturacion = new CabeceraFacturacion();
            cabeceraFacturacion.setPrintDate(printDate);
            cabeceraFacturacion.setReportIdentifier(reportIdentifier);
            cabeceraFacturacion.setTituloReporte(tituloReporte);
            cabeceraFacturacion.setFechaDesde(fechaDesde);
            cabeceraFacturacion.setFechaHasta(fechaHasta);

        }
    };

    reader.setSkippedLinesCallback(skippedLineCallback);

    detalleLineMapper.setLineTokenizer(tokenizerDet);
    detalleLineMapper.setFieldSetMapper(new DetalleFieldSetMapper());
    detalleLineMapper.afterPropertiesSet();
    reader.setLineMapper(detalleLineMapper);

    // Test to check if it is saving correctly data in CabeceraFacturacion
    CabeceraFacturacion cabeceraFacturacion = new CabeceraFacturacion();
    System.out.println("Print Date:"+cabeceraFacturacion.getPrintDate());
    System.out.println("Report Identif: 
    "+cabeceraFacturacion.getReportIdentifier());

    return reader;

}

1 ответ

Решение

Ты прав. Вам нужно использовать skippedLinesCallback обрабатывать пропущенные строки.

Вам необходимо реализовать LineCallbackHandler интерфейс и добавить вашу обработку в методе handleLine.

Интерфейс LineCallbackHandler передает необработанное содержимое строк в файле, который необходимо пропустить. Если linesToSkip установлен в 2, то этот интерфейс вызывается дважды.

Вот как вы можете определить Reader для того же.

Java Config - Spring Batch 4

@Bean
    public FlatFileItemReader<POJO> myReader() {

        return FlatFileItemReader<pojo>().
                .setResource(new FileSystemResource("resources/players.csv"));
                .name("myReader")
                .delimited()
                .delimiter(",")
                .names("pro1,pro2,pro3")
                .targetType(POJO.class)
                .skippedLinesCallback(skippedLinesCallback)             
                .build();

    }
Другие вопросы по тегам