【问题标题】:Spring batch FlatFileItemReader token errorSpring批处理FlatFileItemReader令牌错误
【发布时间】:2021-01-04 13:49:56
【问题描述】:

我的文件系统中有两个 csv 文件,我需要根据某些请求类型使用 Spring Batch 进行处理。

请求类型的文件:EOD(无标题)

12345,BBG
23232,BBG

请求类型的另一个文件:ANCIENT(无标题)

12345,BBG,20201115
23232,BBG,20201115

这两个文件都具有强制性的前两个字段,idsource。 ANCIENT 文件可以选择具有第三和第四字段startDateendDate

如何创建适用于这两个文件的FlatFileItemReader?目前我有类似的东西:

我的 ItemReader 实现读取 csv 文件:

@Bean
@Scope(value = "step", proxyMode = ScopedProxyMode.INTERFACES)
public FlatFileItemReader<FixingDTO> fileReader(@Value("#{jobExecutionContext['type']}") String type) {
    SomeType type = forName(type);
    return new FlatFileItemReaderBuilder<MyDTO>()
            .name("fileReader")
            .resource(new ClassPathResource(MAP.get(type)))
            .delimited()
            .delimiter(",")
            .names("id", "source", "startDate", "endDate")
            .fieldSetMapper(myDTOMapper())
            .build();
}

字段映射器:

public class MyDTOFieldMapper implements FieldSetMapper<MyDTO> {

    @Override
    public MyDTO  mapFieldSet(FieldSet fieldSet) throws BindException {
        MyDTO dto = new MyDTO();

        dto.setId(fieldSet.readString("id"));
        dto.setSource(fieldSet.readString("source"));
        dto.setStartDate(formatDate(fieldSet.readString("startDate")));
        dto.setEndDate(formatDate(fieldSet.readString("endDate")));

        return dto;
    }

    private LocalDate formatDate(String dateString) {
        return LocalDate.parse(dateString, DateTimeFormatter.ofPattern("yyyyMMdd"));
    }
}

运行作业时出现令牌异常:

Caused by: org.springframework.batch.item.file.transform.IncorrectTokenCountException: Incorrect number of tokens found in record: expected 4 actual 2

我想简单地处理行中的任何内容并分配给对象变量。 StartDate 和 endDate 可以为空。

【问题讨论】:

标签: java spring spring-batch


【解决方案1】:

DelimitedLineTokenizer 内部有字段strict(默认值:true),该属性正是您要查找的。您应该将该字段设置为 false。

行为描述:

    /**
     * Public setter for the strict flag. If true (the default) then number of 
     * tokens in line must match the number of tokens defined 
     * (by {@link Range}, columns, etc.) in {@link LineTokenizer}. 
     * If false then lines with less tokens will be tolerated and padded with 
     * empty columns, and lines with more tokens will 
     * simply be truncated.
     * 
     * @param strict the strict flag to set
     */
    public void setStrict(boolean strict) {
        this.strict = strict;
    }

很遗憾,在builder中没有设置严格字段的​​好方法,否则我们可以通过以下方式设置:

@Bean
@Scope(value = "step", proxyMode = ScopedProxyMode.INTERFACES)
public FlatFileItemReader<FixingDTO> fileReader(@Value("#{jobExecutionContext['type']}") String type) {
    SomeType type = forName(type);
    return new FlatFileItemReaderBuilder<MyDTO>()
                .name("fileReader")
                .fieldSetMapper(myDTOMapper())
                .lineTokenizer(new DelimitedLineTokenizer() {
                    {
                        setDelimiter(",");
                        setNames("id", "source", "startDate", "endDate");
                        setStrict(false);
                    }
                })
                .build();
    }

【讨论】:

  • 是的...这对我有用。有没有办法可以用 FlatFileItemReaderBuilder 设置它?
  • 我更新了答案,我删除了一些额外的构建器方法,因为我们使用的是DelimitedLineTokenizer tokenizer。
  • 这对我来说比我拥有的更整洁。干杯
猜你喜欢
  • 1970-01-01
  • 2012-07-30
  • 2018-03-31
  • 1970-01-01
  • 1970-01-01
  • 2012-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多