如何在Spring批处理中分别读取平面文件头和正文

如何在Spring批处理中分别读取平面文件头和正文,spring,spring-boot,spring-batch,flatfilereader,Spring,Spring Boot,Spring Batch,Flatfilereader,我正在用SpringBatch和SpringBoot做一个简单的批处理工作 我需要读取一个平面文件,将头数据(第一行)与主体数据(其余行)分开,以进行单独的业务逻辑处理,然后将所有内容写入一个文件 如您所见,标头有5个参数必须映射到一个类,而正文有12个参数必须映射到另一个类 我首先想到使用FlatFileItemReader并跳过标题。然后使用skippedLinesCallback来处理该行,但我不知道如何处理它 我不熟悉Spring批处理和Java配置。如果有人能帮我为我的问题写一个解决方

我正在用SpringBatch和SpringBoot做一个简单的批处理工作

我需要读取一个平面文件,将头数据(第一行)与主体数据(其余行)分开,以进行单独的业务逻辑处理,然后将所有内容写入一个文件

如您所见,标头有5个参数必须映射到一个类,而正文有12个参数必须映射到另一个类

我首先想到使用FlatFileItemReader并跳过标题。然后使用skippedLinesCallback来处理该行,但我不知道如何处理它

我不熟悉Spring批处理和Java配置。如果有人能帮我为我的问题写一个解决方案,我会非常感谢的

我将输入文件留在这里:

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称为detallefactoracion,我的“头球”POJO称为cabecerafacturation。我想用Detalefacturacion pojo做的读者,所以我可以跳过标题,稍后再处理。。。然而,我不知道如何将标头的数据分配到CabeCerafAction中

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;
public FlatFileItemReader readerDetalleFacturacion(){
FlatFileItemReader=新的FlatFileItemReader();
reader.setLinesToSkip(1);
setResource(新类路径资源(“/inputFiles/GLEO-MN170100-PROCESO01-SUBDFACT-000001.txt”);
DefaultLineMapper-DetalLineMapper=新的DefaultLineMapper();
DelimitedLineTokenizer tokenizerDet=新的DelimitedLineTokenizer(“|”);
setNames(新字符串[]{“fechaEmision”、“tipoDocumento”、“letra”、“nrocoprobante”,
“nRoclient”、“razonSocial”、“cuit”、“montoNetoGP”、“montoNetoG3”,
“montoExento”、“Impustos”、“Montotototal”});
LineCallbackHandler skippedLineCallback=新建LineCallbackHandler(){
@凌驾
公共无效扶手线(字符串线){
字符串[]headerSeparado=line.split(“|”);
字符串printDate=headerSeparado[0];
字符串reportIdentifier=headerSeparado[1];
字符串tituloreport=headerSeparado[2];
字符串fechaDesde=headerSeparado[3];
字符串fechaHasta=headerSeparado[4];
CabeceraFacturacion CabeceraFacturacion=新的CabeceraFacturacion();
cabeceraFacturacion.setPrintDate(打印日期);
cabeCerActuation.setReportIdentifier(reportIdentifier);
cabeceraFacturacion.settituloreport(tituloreport);
cabeceraFacturacion.setFechaDesde(fechaDesde);
赤霞珠藻(赤霞珠藻);
}
};
reader.setSkippedLinesCallback(skippedLineCallback);
setLineTokenizer(TokenizerNet);
setFieldSetMapper(新的DetalleFieldSetMapper());
detalLineMapper.AfterPropertieSet();
reader.setLineMapper(DetalLineMapper);
//测试以检查是否正确地将数据保存在机柜中
CabeceraFacturacion CabeceraFacturacion=新的CabeceraFacturacion();
System.out.println(“打印日期:+CABECERafacturation.getPrintDate());
System.out.println(“报告标识,如果:
“+cabeceraFacturacion.getReportIdentifier());
返回读取器;

}你是对的。您需要使用
skippedLinesCallback
来处理跳过行

您需要实现
LineCallbackHandler
接口,并在handleLine方法中添加处理

LineCallbackHandler接口传递文件中要跳过的行的原始行内容。如果linesToSkip设置为2,则调用此接口两次

这就是如何为相同的对象定义读取器的方法

Java配置-Spring批处理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();

    }
@Bean
公共FlatFileItemReader myReader(){
返回FlatFileItemReader()。
.setResource(新文件系统资源(“resources/players.csv”);
.name(“myReader”)
.delimited()
.分隔符(“,”)
.名称(“项目1、项目2、项目3”)
.targetType(POJO.class)
.SkippedLineScalBack(SkippedLineScalBack)
.build();
}

非常感谢Niraj的回答。这是我尝试过的,但我仍然不知道如何将头数据存储在一个pojo中,将主体数据存储在另一个pojo中。因为当我定义FlatFileItemReader时,我在中只使用了一个pojo。如果您将linesToSkip设置为1,那么对于该行(标题行),将调用LineCallbackHandler.handleLine方法。批处理框架将把原始行内容传递给该方法。然后你需要根据你的需要解析这行代码。到那一点我都明白。我再次更新了代码。我用测线器和标记器来读这行代码。这是阅读的方式吗?因为在测试中,我没有检查它是否正确保存了数据,两个参数都给了我null,我明白了。这只是一条原始的线。然后我可以使用line.split(“|”)并用set保存参数。非常感谢你,尼拉杰!不客气。。。你能接受答案吗?这也会帮助其他可能面临同样问题的人。谢谢