Ubuntu服务器上Java字符串空格替换异常问题排查与解决
CSV导入跨Windows/Ubuntu环境异常的原因与解决方法
问题描述
通过CSV文件逐行读取数据并映射到实体类,数字字段需替换空格后转换为BigDecimal。本地Windows及Windows服务器部署正常,但Ubuntu服务器经Jenkins构建部署后功能异常。核心转换代码如下:
public static <T> T transformCsvToData(String ligneCsv, Class clazz, String[] fieldNames) { T t = null; try { if (!StringUtils.isBlank(ligneCsv)) { String[] listValues = ligneCsv.split(String.valueOf(DEFAULT_SEPARATOR)); t = (T) clazz.newInstance(); for (int i=0; i<fieldNames.length; i++) { String fieldName = fieldNames[i]; String stringValue = listValues.length > i ? listValues[i] : null; PropertyDescriptor pd = new PropertyDescriptor(fieldName, clazz); Class fieldType = pd.getPropertyType(); // verifier qu'il existe une methode set if (pd.getWriteMethod() != null && !"class".equals(pd.getName())) { // recuperer la methode set Method writeMethod = pd.getWriteMethod(); Object castedValue = null; if (StringUtils.isNotBlank(stringValue)) { try { stringValue = stringValue.trim(); if (fieldType == String.class) { castedValue = stringValue; } else if (fieldType == Boolean.class) { castedValue = Boolean.valueOf(stringValue.toLowerCase()); } else if (fieldType == Date.class) { castedValue = new SimpleDateFormat(FORMAT_INPUT_DATE, Locale.FRANCE).parse(stringValue); } else if (fieldType == Integer.class) { castedValue = Integer.valueOf(stringValue); } else { stringValue = stringValue.replace(",", ".").replace("%", "").replace("\u00A0", "").replaceAll("\\s+", "").replaceAll(" ", ""); if (fieldType == BigDecimal.class) { castedValue = new BigDecimal(stringValue); } else if (fieldType == Long.class) { castedValue = Long.valueOf(stringValue); } else if (fieldType == Double.class) { castedValue = Double.valueOf(stringValue); } } } catch (NumberFormatException | ParseException ex) { castedValue = null; } } writeMethod.invoke(t, castedValue); } } } } catch (Exception e) { e.printStackTrace(); return null; } return t; }
环境差异分析
导致跨平台异常的核心差异点如下:
- 字符编码不一致:Windows默认使用GBK/GB2312编码,Ubuntu默认UTF-8。若CSV文件编码与读取时的系统默认编码不匹配,会出现乱码,导致数字字段混入不可见特殊字符,触发BigDecimal转换失败。
- 换行符差异:Windows换行符为
\r\n,Ubuntu为\n。手动逐行读取时,若未处理残留的\r,会导致字段值末尾带无效字符,引发数字转换异常。 - 空白字符类型差异:Linux环境中可能存在更多Unicode空白字符(如
\u2007、\u202F),原代码仅处理了\u00A0和普通空格,未覆盖所有空白场景。 - Jenkins构建Locale影响:Jenkins在Ubuntu上的默认Locale可能与Windows不同,间接影响字符串处理或格式化逻辑。
解决方法
1. 统一字符编码
读取CSV文件时显式指定编码(推荐UTF-8),避免依赖系统默认编码:
BufferedReader reader = new BufferedReader( new InputStreamReader(new FileInputStream(csvFile), StandardCharsets.UTF_8) );
同时确保源CSV文件统一使用UTF-8编码生成。
2. 统一换行符处理
读取每行后,彻底清理换行相关字符:
String ligneCsv = reader.readLine(); if (ligneCsv != null) { ligneCsv = ligneCsv.replace("\r", "").trim(); }
3. 增强空白字符处理逻辑
替换原代码中数字字段的空白处理逻辑,用正则匹配所有Unicode空白字符:
// 替换所有Unicode空白字符,覆盖Linux下的特殊空白类型 stringValue = stringValue.replace(",", ".").replace("%", "") .replaceAll("\\p{Space}+", "");
\p{Space}会匹配所有Unicode空白字符,包括空格、制表符、换行符等,确保彻底清理无效字符。
4. Jenkins构建时指定编码
在Jenkins构建脚本中添加编码参数,确保编译打包使用统一编码:
# Maven构建示例 mvn clean install -Dfile.encoding=UTF-8
或在Jenkins项目配置中设置环境变量LANG=en_US.UTF-8,避免Locale影响。
5. 替换为成熟CSV解析库
手动解析CSV容易遗漏跨平台细节,推荐使用OpenCSV或Apache Commons CSV,这类库已内置跨平台编码、换行符、字段分割处理:
// OpenCSV示例 CSVReader reader = new CSVReaderBuilder(new FileReader(csvFile)) .withSeparator(DEFAULT_SEPARATOR) .build(); String[] nextLine; while ((nextLine = reader.readNext()) != null) { // 直接获取处理后的字段数组,无需手动分割 }
内容的提问来源于stack exchange,提问作者Mohamed Laajili
相关产品推荐
相关产品推荐

