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

RTF模板VelocityContext替换俄文字符乱码问题求助(Java+SpringBoot3+Apache POI)

解决RTF模板替换俄文占位符乱码问题

问题根源

模板原有俄文正常,但动态插入的俄文乱码,本质是Apache POI处理RTF时,未将UTF-8字符串转换为RTF兼容的编码格式:

  • 模板本身的俄文已被RTF正确编码(如CP1251或UTF-8转义)
  • 动态替换的文本直接以UTF-8写入RTF,而Word/LibreOffice解析RTF时默认使用ANSI编码(如CP1252),导致俄文被错误解析

解决方案

1. 对替换文本进行RTF编码转义

将俄文字符转换为RTF标准的十六进制转义序列,确保Office软件能正确识别:

public static String escapeRtf(String text) {
    StringBuilder rtfText = new StringBuilder();
    for (char c : text.toCharArray()) {
        // 非ASCII字符转成RTF的\u转义格式
        if (c > 127) {
            rtfText.append("\\uc0\\u").append((int) c).append("?");
        } else {
            rtfText.append(c);
        }
    }
    return rtfText.toString();
}

使用时,先转义待替换的俄文文本,再执行占位符替换。

2. 使用HWPF API进行原生替换(避免直接操作RTF字符串)

不要直接读取RTF为字符串替换,而是用Apache POI的HWPFDocument API遍历文档内容,确保编码处理正确:

try (InputStream templateStream = new FileInputStream("template.rtf")) {
    HWPFDocument rtfDoc = new HWPFDocument(templateStream);
    Range docRange = rtfDoc.getRange();
    
    // 转义俄文文本后替换占位符
    String russianText = escapeRtf("русские слова.");
    docRange.replaceText("{RUSSIAN_PLACEHOLDER}", russianText);
    
    try (OutputStream outputStream = new FileOutputStream("output.rtf")) {
        rtfDoc.write(outputStream);
    }
} catch (IOException e) {
    e.printStackTrace();
}

3. 修正RTF文档的编码声明

检查RTF模板开头的编码标记,将\ansi替换为\utf8,确保Office软件以UTF-8解析整个文档:

  • 打开RTF模板(用文本编辑器),找到开头的{\rtf1\ansi,改为{\rtf1\utf8
  • 若使用代码修改,可在读取RTF前先替换头部的编码声明

4. 升级Apache POI版本

确保使用5.2.5及以上版本的Apache POI,旧版本存在RTF编码处理的已知bug,升级后可解决部分编码兼容问题。

验证

替换后生成的RTF文件:

  • 在Postman中仍能正常显示俄文
  • 用Word/LibreOffice打开时,动态插入的俄文与模板原有俄文一致

内容的提问来源于stack exchange,提问作者newbor

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 23:17:34