使用FlatFileItemWriter导出CSV时含逗号字段列错乱的解决方案咨询
解决CSV字段含逗号导致拆分错位的简便方法
不用重写现有代码,只需要修改FlatFileItemWriter里的DelimitedLineAggregator配置,把含特殊字符的字段用引号包裹即可,Spring Batch本身提供了现成支持:
方法一:给所有字段添加引号(快速解决)
修改你代码里的flatFileItemWriter1()方法,在DelimitedLineAggregator的初始化块里添加setQuoteCharacter('"'),所有字段会被双引号包裹,包含逗号的字段就不会被错误拆分:
@StepScope @Bean public FlatFileItemWriter<Invoice> flatFileItemWriter1() { log.info("Initializing Writer"); FlatFileItemWriter<Invoice> flatFileItemWriter1 = new FlatFileItemWriter<>(); flatFileItemWriter1.setResource(new FileSystemResource("random location/name.csv")); flatFileItemWriter1.setHeaderCallback(new FlatFileHeaderCallback() { @Override public void writeHeader(Writer writer) throws IOException { // 可选:给表头也加引号,保持格式一致 writer.write("\"Segment 1\", \"Vendor Name\", \"Invoice Num\""); } }); flatFileItemWriter1.setLineAggregator(new DelimitedLineAggregator<Invoice>(){ { // 设置引号字符,所有字段自动被双引号包裹 setQuoteCharacter('"'); setFieldExtractor(new BeanWrapperFieldExtractor<Invoice>(){ { setNames(new String[]{"segment1", "vendorName", "invoiceNum"}); } }); } }); return flatFileItemWriter1; }
方法二:仅给指定字段添加引号(更灵活)
如果你只想给可能包含逗号的字段(比如vendorName)添加引号,用QuoteFieldExtractorWrapper包装原字段提取器,指定需要引号的字段:
@StepScope @Bean public FlatFileItemWriter<Invoice> flatFileItemWriter1() { log.info("Initializing Writer"); FlatFileItemWriter<Invoice> flatFileItemWriter1 = new FlatFileItemWriter<>(); flatFileItemWriter1.setResource(new FileSystemResource("random location/name.csv")); flatFileItemWriter1.setHeaderCallback(new FlatFileHeaderCallback() { @Override public void writeHeader(Writer writer) throws IOException { writer.write("Segment 1, Vendor Name, Invoice Num"); } }); // 定义原字段提取器 BeanWrapperFieldExtractor<Invoice> fieldExtractor = new BeanWrapperFieldExtractor<>(); fieldExtractor.setNames(new String[]{"segment1", "vendorName", "invoiceNum"}); // 包装为带引号的提取器,指定需要加引号的字段 QuoteFieldExtractorWrapper<Invoice> quotedFieldExtractor = new QuoteFieldExtractorWrapper<>(); quotedFieldExtractor.setDelegate(fieldExtractor); quotedFieldExtractor.setNamesToQuote(new String[]{"vendorName"}); // 仅给vendorName加引号 quotedFieldExtractor.setQuoteCharacter('"'); flatFileItemWriter1.setLineAggregator(new DelimitedLineAggregator<Invoice>(){ { setFieldExtractor(quotedFieldExtractor); } }); return flatFileItemWriter1; }
这两种方法都不需要改动Reader、Job或Step的配置,仅修改Writer的几行代码就能解决问题,完全符合你"无需重写全部代码"的需求。
内容的提问来源于stack exchange,提问作者user19881976
相关产品推荐
相关产品推荐

