Spring Batch IncorrectTokenCountException阅读器在csv文件中接受多列

时间:2019-02-24 17:29:46

标签: csv spring-batch

我以前从未使用过Spring Batch,我有一个csv文件,我需要读取特定模型的所有列,但是我有很多例外。

csv文件有8个字段。如果所有五个字段都在那里,则文件处理效果很好。但是如果误输入了8个字段,则如下所示:

c1; c2; C3; C4; C5; C6; C7; C8 // IT工作 c1; C3; C7 //无效:程序崩溃

错误是:由以下原因引起:org.springframework.batch.item.file.transform.IncorrectTokenCountException:记录中发现的令牌数量不正确:预期为3个实际8。

我的代码:

@Bean
public Step Step2(StepBuilderFactory stepBuilders) throws IOException {
    System.out.println("cecStep2");
    return stepBuilders.get("fileReject")
            .<CSCivique, String>chunk(100)
            .reader(reader())
            .processor(processor2FileReject())
            .writer(writer2())
            .build();
}

@Bean
public FlatFileItemReader<CSCivique> reader() throws IOException{

    try {


    return new FlatFileItemReaderBuilder<CSCivique>().name("personItemReader")
                                .resource(new ClassPathResource(confFile ()))
                                .delimited()
                                .delimiter(";")
                                .names(new String[] { "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8" })
                                .targetType(CSCivique.class)
                                .strict(false)
                                .build();

    }catch(Exception e) {
        System.out.println("----------- Exception reader() --------------");
        return null ;
    }


}

我想在文件拒绝中保存行,例如: c1; C3; C7:请检查字段数

谢谢。

2 个答案:

答案 0 :(得分:0)

这是here中记录的正常行为。您将阅读器配置为期望包含8列:

.names(new String[] { "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8" })

因此,令牌数量不同的任何行都将被拒绝。

您可以做的是使用容错步骤,并使用以下命令跳过这些行:

@Bean
public Step Step2(StepBuilderFactory stepBuilders) throws IOException {
    System.out.println("cecStep2");
    return stepBuilders.get("fileReject")
            .<CSCivique, String>chunk(100)
            .reader(reader())
            .processor(processor2FileReject())
            .writer(writer2())
            .faultTolerant()
            .skip(FlatFileParseException.class)
            .skipLimit(10)
            .build();
}

使用此配置,这些行将被跳过,您的工作不会失败。之后,您可以使用StepExecution#getSkipCount获取跳过计数。

否则,您可以创建自己的LineTokenizer并根据需要对行进行标记。

答案 1 :(得分:0)

明白这个答案迟到了 2 年,最近遇到了这个问题,我想支持接受和处理部分行。

在 Spring 批处理中,DelimitedLineTokenizer 分词器(以及 Spring 批处理中的大多数其他标准分词器)扩展了 AbstractLineTokenizer 类,该类具有属性 strict,如果设置得太高,true 将如果令牌数量不匹配,则失败。相反,如果该属性设置得太 false,那么它将忽略额外/缺失的标记。

https://docs.spring.io/spring-batch/docs/current/api/org/springframework/batch/item/file/transform/AbstractLineTokenizer.html

这就是我在 XML 中配置我的平面文件阅读器的方式

<bean class="org.springframework.batch.item.file.FlatFileItemReader" id="add-item-reader" scope="step">
<property name="resource" value="${file.path}"/>
<property name="lineMapper">
    <bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
        <property name="fieldSetMapper" ref="fset-mapper"/>
        <property name="lineTokenizer">
            <bean class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
                <property name="delimiter" value="|"/>
                <property name="names" value="tokens...."/>
                <property name="strict" value="false"/>
            </bean>
        </property>
    </bean>
</property>