Spring Batch如何读取含空格与点号的CSV字段?
Spring Batch读取含空格/点号字段的CSV解析问题解决方法
问题根源
解析错误主要来自两个核心问题:
- 默认的
DelimitedLineTokenizer未配置引号处理逻辑,导致带空格的字段被错误拆分; - 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
相关产品推荐
相关产品推荐

