CSV逗号分隔符与多地区数字格式的冲突解决方案需求
问题根因
- 导出时使用
StringEscapeUtils.escapeCsv()会自动给包含分隔符,的数值字段包裹双引号,属于标准CSV格式 - 导入时直接调用
String.split()拆分不会识别CSV的引号转义规则,将引号内作为数值一部分的逗号误判为字段分隔符,导致拆分结果错误
解决方案
不需要修改原有分隔符,仅需调整导入拆分逻辑、补充导出优化即可,具体实现如下:
导出侧优化(可选,避免生成冗余字段)
原有代码在行尾多拼接了一次分隔符,会导致每行末尾生成多余空字段,调整后代码:
public static final String LINE_SEPERATOR = "\n"; public static final String DELIMITER = ","; protected void writeEntry(final Writer writer, final EntryDTO entry) throws IOException { final StringBuilder csvContent = new StringBuilder(); csvContent.append(StringEscapeUtils.escapeCsv(entry.getProduct().getName())).append(DELIMITER) .append(StringEscapeUtils.escapeCsv(entry.getTotalWeight())); writer.write(csvContent.toString()); writer.write(LINE_SEPERATOR); }
导入侧拆分逻辑改造(必改)
方案1:使用成熟CSV解析工具(推荐)
推荐使用Apache Commons CSV等成熟工具,自动适配CSV转义规则,示例代码:
CSVFormat csvFormat = CSVFormat.DEFAULT.withDelimiter(DELIMITER.charAt(0)); try (CSVParser csvParser = CSVParser.parse(line, csvFormat)) { CSVRecord record = csvParser.getRecords().get(0); // 索引0为商品名称,索引1为重量完整字符串 String productName = record.get(0); String totalWeight = record.get(1); }
方案2:手动实现带引号识别的拆分逻辑(无需额外依赖)
如果不想引入第三方依赖,可以自己实现简单的CSV拆分逻辑:
private List<String> splitCsvLine(String line, char delimiter) { List<String> fieldList = new ArrayList<>(); StringBuilder currentField = new StringBuilder(); boolean insideQuotes = false; for (char c : line.toCharArray()) { if (c == '"') { insideQuotes = !insideQuotes; } else if (c == delimiter && !insideQuotes) { fieldList.add(currentField.toString().trim()); currentField.setLength(0); } else { currentField.append(c); } } fieldList.add(currentField.toString().trim()); return fieldList; } // 调用示例 final List<String> attributes = splitCsvLine(line, DELIMITER.charAt(0));
多地区数值解析兼容
拿到完整的重量字符串后,根据文件所属地区调用对应本地化解析逻辑即可:
// 英国地区数值解析 NumberFormat ukNumberFormat = NumberFormat.getInstance(Locale.UK); double ukWeight = ukNumberFormat.parse(totalWeight).doubleValue(); // 德国地区数值解析 NumberFormat deNumberFormat = NumberFormat.getInstance(Locale.GERMANY); double deWeight = deNumberFormat.parse(totalWeight).doubleValue();
内容的提问来源于stack exchange,提问作者Rodik
相关产品推荐
相关产品推荐

