我以前从未使用过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:请检查字段数
谢谢。
答案 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
,那么它将忽略额外/缺失的标记。
这就是我在 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>