【问题标题】:Spring batch IncorrectTokenCountException reader accept multi colomn in csv fileSpring batch Incorrect Token CountException reader接受csv文件中的多列
【发布时间】:2019-07-18 04:04:24
【问题描述】:

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

csv 文件有 8 个字段。如果所有五个字段都存在,则文件处理运行良好。但是如果不小心输入了8个字段,如下图:

c1;c2;C3;C4;C5;C6;C7;C8 // 它工作 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:请检查字段数

谢谢。

【问题讨论】:

    标签: csv spring-batch


    【解决方案1】:

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

    在 Spring 批处理中,DelimitedLineTokenizer 标记器(以及 Spring 批处理中的大多数其他标准标记器)扩展了具有属性 strictAbstractLineTokenizer 类,如果设置太多,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>
    

    【讨论】:

      【解决方案2】:

      这是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 并根据需要标记该行。

      【讨论】:

      • 谢谢你,Mahmoud,我可以将那些跳过的行保存在拒绝文件 csv 中吗?你有代码示例吗?
      • 是的,您可以使用SkipListener 执行此操作。这是一个示例:stackoverflow.com/a/54648302/5019386。如果这有帮助,请接受答案。希望它有所帮助:-)
      • 您好 Mahmoud,如何在 ArryLis 中读取 csv 文件并保存 csv 文件中跳过的行?谢谢。
      • 你好,把每一列放在一个盒子里检查它的内容(是否为空)并将这一行写入拒绝文件。
      • 好的,我明白了。您可以使用PassThroughFieldSetMapper,它将为您提供FieldSet(类似于JDBC ResultSet)。字段集允许您使用getValues 方法获取值数组。要编写跳过的行,您需要自定义 SkipListener,您可以在此处找到示例:stackoverflow.com/a/51985616/5019386(只需将 System.out 替换为写入文件即可)。
      猜你喜欢
      • 1970-01-01
      • 2018-12-22
      • 2016-11-25
      • 1970-01-01
      • 1970-01-01
      • 2018-08-10
      • 2023-03-15
      • 2016-04-15
      • 2012-10-02
      相关资源
      最近更新 更多