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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 07:26:00