11.5 多行记录
虽然通常的flat文件,每个记录限制是一行,但是一个文件可能与多种格式多行记录,这是很常见的.以下摘录文件说明了这一点:
HEA;0013100345;2007-02-15
NCU;Smith;Peter;;T;20014539;F
BAD;;Oak Street 31/A;;Small Town;00235;IL;US
FOT;2;2;267.34
之间的所有行从’HEA’开始和从’FOT’开始被认为是一个记录.有一些注意事项,必须正确地处理这种情况:
不是一次读取一条记录,而是ItemReader必须读取多行的每一行记录作为一个分组.这样它就可以被完整的传递到ItemWriter.
每一行可能需要标记不同的类型.
因为单行记录跨越多行,我们可能不知道有多少行,所以ItemReader必须总是小心的读一个完整的记录.为了做到这一点,一个自定义ItemReader,应该实现一个FlatFileItemReader的包装器
<bean id="itemReader" class="org.spr...MultiLineTradeItemReader">
<property name="delegate">
<bean class="org.springframework.batch.item.file.FlatFileItemReader">
<property name="resource" value="data/iosample/input/multiLine.txt" />
<property name="lineMapper">
<bean class="org.spr...DefaultLineMapper">
<property name="lineTokenizer" ref="orderFileTokenizer"/>
<property name="fieldSetMapper">
<bean class="org.spr...PassThroughFieldSetMapper" />
</property>
</bean>
</property>
</bean>
</property>
</bean>
确保正确标记的每一行,特别是重要的固定长度的输入,可以将PatternMatchingCompositeLineTokenizer委托于FlatFileItemReader.见章节 “Multiple Record Types within a Single File”中的更多的细节.这个委托reader,会将FieldSet传递到PassThroughFieldSetMapper再返回每一行到ItemReader 包装器中.
<bean id="orderFileTokenizer" class="org.spr...PatternMatchingCompositeLineTokenizer">
<property name="tokenizers">
<map>
<entry key="HEA*" value-ref="headerRecordTokenizer" />
<entry key="FOT*" value-ref="footerRecordTokenizer" />
<entry key="NCU*" value-ref="customerLineTokenizer" />
<entry key="BAD*" value-ref="billingAddressLineTokenizer" />
</map>
</property>
</bean>
这个包装器必须能够识别结束的记录,所以它可以不断调用delegate的read()方法直到结束.
对于读取的每一行,该wrapper应该绑定返回的item,一旦读到footer结束,item应该传递给ItemProcessor和ItemWriter返回.
private FlatFileItemReader