【问题标题】:FlatFileItemReader tab delimiter not workingFlatFileItemReader 制表符分隔符不起作用
【发布时间】:2018-08-08 04:39:09
【问题描述】:

我从春天开始检查这个项目: https://github.com/spring-guides/gs-batch-processing

来源:https://spring.io/guides/gs/batch-processing/

我将“sample-data.csv”中的“,”替换为“tab”:

Jill    Doe
Joe Doe
Justin  Doe
Jane    Doe
John    Doe

然后我将新的分隔符添加到阅读器:

@Bean
public FlatFileItemReader<Person> reader() {
    return new FlatFileItemReaderBuilder<Person>()
        .name("personItemReader")
        .resource(new ClassPathResource("sample-data.csv"))
        .delimited()
        .delimiter(DelimitedLineTokenizer.DELIMITER_TAB) // NEW DELIMITER
        .names(new String[]{"firstName", "lastName"})
        .fieldSetMapper(new BeanWrapperFieldSetMapper<Person>() {{
            setTargetType(Person.class);
        }})
        .build();
}

当我启动我得到这个错误:

Caused by: org.springframework.batch.item.file.transform.IncorrectTokenCountException: Incorrect number of tokens found in record: expected 2 actual 1
    at org.springframework.batch.item.file.transform.AbstractLineTokenizer.tokenize(AbstractLineTokenizer.java:142) ~[spring-batch-infrastructure-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.batch.item.file.mapping.DefaultLineMapper.mapLine(DefaultLineMapper.java:43) ~[spring-batch-infrastructure-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.batch.item.file.FlatFileItemReader.doRead(FlatFileItemReader.java:180) ~[spring-batch-infrastructure-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    ... 50 common frames omitted

我尝试过使用“@”分隔符 -> 它可以工作。 由于某种原因,我无法使用制表符分隔符...

当然,在我的实际项目中,我有一个带有“制表符”分隔符的输入文件...

这里有什么解决办法吗?

【问题讨论】:

  • 你的第二行看起来很奇怪:Joe Doe 也许标记器抱怨这个?
  • 这个问题有一个未解决的票:jira.spring.io/browse/BATCH-2738。下个版本会修复

标签: java spring spring-batch


【解决方案1】:

您不能那样设置制表符分隔符。由于制表符 ('\t') 不包含任何实际文本,它会被 FlatFileItemReaderBuilder.java 中的静态 DelimitedBuilder 类中的 DelimitedLineTokenizer 忽略。可以使用您在问题中给出的上述代码设置任何非空白分隔符。

FlatFileItemReaderBuilder sourceCode

这就是LineTokenizer 实例在FlatFileItemReaderBuilder.java 中的构建方式。

public DelimitedLineTokenizer build() {
        Assert.notNull(this.fieldSetFactory, "A FieldSetFactory is required.");
        Assert.notEmpty(this.names, "A list of field names is required");

        DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer();

        tokenizer.setNames(this.names.toArray(new String[this.names.size()]));

        // the hasText ignores the tab delimiter.

        if(StringUtils.hasText(this.delimiter)) {
            tokenizer.setDelimiter(this.delimiter);
        }
// more code

因此,要解决此问题,您需要提供类型为 DelimitedLineTokenizer 的 bean,显式配置了制表符分隔符。

在你的 spring 配置文件中使用下面的代码来设置制表符分隔符:

@Bean
public FlatFileItemReader<Person> reader() {
    return new FlatFileItemReaderBuilder<Person>().name("personItemReader")
            .resource(new ClassPathResource("sample-data.csv"))
            .lineMapper(lineMapper()).build();
}

@Bean
public DefaultLineMapper<Person> lineMapper(){
      DefaultLineMapper<Person> lineMapper = new DefaultLineMapper<>();
      lineMapper.setLineTokenizer(lineTokenizer());
      lineMapper.setFieldSetMapper(new BeanWrapperFieldSetMapper<Person>() {
                {
                    setTargetType(Person.class);
                }
            });
      return lineMapper;
}

@Bean
public DelimitedLineTokenizer lineTokenizer() {
    DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer(DelimitedLineTokenizer.DELIMITER_TAB);
    tokenizer.setNames(new String[] { "firstName", "lastName" });
    return tokenizer;
}

【讨论】:

  • 完美:我明白我错在哪里,而且效果很好。谢谢
  • @Tyvain 很高兴听到它有帮助。
【解决方案2】:

简单的方法:

@Bean
public FlatFileItemReader<Person> reader() {
    return new FlatFileItemReaderBuilder<Person>()
            .name("personItemReader")
            .resource(new ClassPathResource("sample-data.csv"))
            .lineTokenizer(new DelimitedLineTokenizer(DelimitedLineTokenizer.DELIMITER_TAB) {{
                setNames(new String[]{"firstName", "lastName"});
            }})
            .fieldSetMapper(new BeanWrapperFieldSetMapper<Person>() {{
                setTargetType(Person.class);
            }})
            .build();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-09
    • 2012-12-09
    相关资源
    最近更新 更多