Skip to content

Latest commit

 

History

History
80 lines (65 loc) · 3.47 KB

File metadata and controls

80 lines (65 loc) · 3.47 KB

##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

delegate;

public Trade read() throws Exception {
    Trade t = null;

    for (FieldSet line = null; (line = this.delegate.read()) != null;) {
        String prefix = line.readString(0);
        if (prefix.equals("HEA")) {
            t = new Trade(); // Record must start with header
        }
        else if (prefix.equals("NCU")) {
            Assert.notNull(t, "No header was found.");
            t.setLast(line.readString(1));
            t.setFirst(line.readString(2));
            ...
        }
        else if (prefix.equals("BAD")) {
            Assert.notNull(t, "No header was found.");
            t.setCity(line.readString(4));
            t.setState(line.readString(6));
          ...
        }
        else if (prefix.equals("FOT")) {
            return t; // Record must end with footer
        }
    }
    Assert.isNull(t, "No 'END' was found.");
    return null;
}