You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Batch如何读取含空格与点号的CSV字段?

Spring Batch读取含空格/点号字段的CSV解析问题解决方法

问题根源

解析错误主要来自两个核心问题:

  1. 默认的DelimitedLineTokenizer未配置引号处理逻辑,导致带空格的字段被错误拆分;
  2. CSV列名包含空格、点号,与TestDTO的驼峰属性名无法直接匹配,BeanWrapperFieldSetMapper无法完成属性映射。

修正方案

1. 配置Tokenizer正确解析带引号字段

给DelimitedLineTokenizer指定引号字符,并开启忽略字段前的空格,确保带空格的字段被完整读取。

2. 实现列名到DTO属性的映射

使用MappingFieldSetMapper替代BeanWrapperFieldSetMapper,手动定义CSV列名与DTO属性的映射关系,解决空格、点号导致的名称不匹配问题。

3. 修复代码中的其他错误

  • 修正@Bean注解的引号闭合问题;
  • 处理csvFileResource返回数组与FlatFileItemReader单资源的适配(或改用MultiResourceItemReader读取多文件);
  • 修正泛型类型不匹配问题。

修改后的完整代码

@Configuration
public class TestReaderConfig {

    @Bean("testReader")
    public ItemReader<TestDTO> csvFileReader() {
        // 读取多个CSV文件用MultiResourceItemReader
        MultiResourceItemReader<TestDTO> multiReader = new MultiResourceItemReader<>();
        try {
            multiReader.setResources(csvFileResource());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        multiReader.setDelegate(flatFileItemReader());
        return multiReader;
    }

    @Bean
    public FlatFileItemReader<TestDTO> flatFileItemReader() {
        FlatFileItemReader<TestDTO> reader = new FlatFileItemReader<>();
        reader.setLinesToSkip(1); // 跳过表头
        reader.setLineMapper(csvLineMapper());
        return reader;
    }

    @Bean
    public DefaultLineMapper<TestDTO> csvLineMapper() {
        DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer();
        tokenizer.setQuoteCharacter('"'); // 指定CSV字段的引号分隔符
        tokenizer.setIgnoreLeadingWhiteSpace(true); // 忽略字段前的空格
        tokenizer.setNames("Name", "Last name", "Date", "Street. Name"); // 与CSV表头完全一致

        // 自定义字段映射,解决列名与DTO属性名不匹配问题
        MappingFieldSetMapper<TestDTO> fieldSetMapper = new MappingFieldSetMapper<>();
        fieldSetMapper.setTargetType(TestDTO.class);
        fieldSetMapper.setFieldMap(Map.of(
                "Name", "name",
                "Last name", "lastName",
                "Date", "date",
                "Street. Name", "streetName"
        ));

        DefaultLineMapper<TestDTO> lineMapper = new DefaultLineMapper<>();
        lineMapper.setLineTokenizer(tokenizer);
        lineMapper.setFieldSetMapper(fieldSetMapper);

        return lineMapper;
    }

    @Bean
    public Resource[] csvFileResource() throws IOException {
        Resource[] resources = new PathMatchingResourcePatternResolver().getResources("file:input/*.csv");
        if (resources.length == 0) {
            throw new FileNotFoundException("指定目录下未找到CSV文件");
        }
        return resources;
    }
}

补充说明

  • 确保TestDTO的属性名与映射中的目标名称一致(如name、lastName、date、streetName);
  • 如果只需要读取单个文件,可将csvFileReader改为直接使用FlatFileItemReader,并设置reader.setResource(csvFileResource()[0]);
  • 若CSV中存在特殊字符或复杂格式,可进一步自定义LineTokenizer或FieldSetMapper的逻辑。

内容的提问来源于stack exchange,提问作者Henrique Vital

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 14:23:11