Spring 批处理 LineMapper 的可选多行条目

Optional Multi-line Entry for Spring Batch LineMapper

我有一个通常具有以下格式的文件:

property_A_1@property_B_1@property_C_1@property_D_1
property_A_2@property_B_2@property_C_2@property_D_2
property_A_3@property_B_3@property_C_3@property_D_3

这应该映射到具有四个属性的自定义 class,@ 作为分隔符。但是,在某些情况下 property_B 可能包含换行符作为其字符的一部分,例如:

property_A_1@property_B_1@property_C_1@property_D_1
property_A_2@property_B_2_i
property_B_2_ii
property_B_2_iii
property_B_2_iiii@property_C_2@property_D_2
property_A_3@property_B_3@property_C_3@property_D_3

这些行的数量可以变化并且不固定。在这种情况下,我仍然需要像以前一样映射第二个条目,除了 property_b_2 应该包含第一个 @ 和第二个 @.

之间的数据。

如果我可以用空格替换它们,我可以忍受没有新行,所以假设实际条目看起来像:

property_A_2@property_B_2_i property_B_2_ii property_B_2_iii@property_B_2_iiii@property_C_2@property_D_2

有没有办法用 ItemReaderLineMapper 来完成这个?

我通过覆盖 ItemReaderDefaultRecordSeparatorPolicy#isEndOfRecord() 解决了这个问题。我还需要阅读未终止的引号检查,因为内容可能有一对不均匀的引号字符:

itemReader.setRecordSeparatorPolicy(new DefaultRecordSeparatorPolicy() {

    private static final String CONTINUATION = "\";

    private String continuation = CONTINUATION;
    private String final String delimiter ="@";

    @Override
    public boolean isEndOfRecord(String line) {
        return StringUtils.countOccurrencesOf(line, delimiter) >=3 &&
               !isQuoteUnterminated(line) && 
               !isContinued(line);
    }

    private boolean isQuoteUnterminated(String line) {
        return false;
    }

    private boolean isContinued(String line) {
        if (line == null) {
            return false;
        }
        return line.trim().endsWith(continuation);
    }
});