根据规范,这里有一些经过测试和工作的java代码:
public static String escape(String s){
if (s == null) return s;
int len = s.length();
StringBuilder sb = new StringBuilder(len);
for (int i = 0; i < len; i++){
char c = s.charAt(i);
if (c >= 0x20 && c < 0x80){
if (c == '\\' || c == '{' || c == '}'){
sb.append('\\');
}
sb.append(c);
}
else if (c < 0x20 || (c >= 0x80 && c <= 0xFF)){
sb.append("\'");
sb.append(Integer.toHexString(c));
}else{
sb.append("\\u");
sb.append((short)c);
sb.append("??");//two bytes ignored
}
}
return sb.toString();
}
重要的是,您需要在转义的 uncode 之后附加 2 个字符(接近 unicode 字符或只使用 ?)。因为 unicode 占用 2 个字节。
规范还说,如果代码点大于 32767,您应该使用负值,但在我的测试中,如果您不使用负值也没关系。
这是规格:
\uN 此关键字表示单个 Unicode 字符,它没有基于当前 ANSI 代码页的等效 ANSI 表示。N 表示以十进制数表示的 Unicode 字符值。此关键字后紧跟 ANSI 表示中的等效字符。这样,老读者会忽略 \uN 关键字并正确地选择 ANSI 表示。当遇到这个关键字时,读者应该忽略接下来的 N 个字符,其中 N 对应于遇到的最后一个 \ucN 值。
与所有 RTF 关键字一样,可能存在关键字终止空格(在 ANSI 字符之前),该空格不计入要跳过的字符中。虽然这不太可能发生(或推荐),但 \bin 关键字、其参数和随后的二进制数据被视为一个字符以用于跳过目的。如果在扫描可跳过数据时遇到 RTF 范围分隔符(即左大括号或右大括号),则认为可跳过数据在分隔符之前结束。这使得读者可以执行一些基本的错误恢复。要在可跳过数据中包含 RTF 定界符,它必须使用适当的控制符号(即用反斜杠转义)表示为纯文本。出于计算可跳过字符的目的,任何 RTF 控制字或符号都被视为单个字符。
An RTF writer, when it encounters a Unicode character with no corresponding ANSI character, should output \uN followed by the best ANSI representation it can manage. Also, if the Unicode character translates into an ANSI character stream with count of bytes differing from the current Unicode Character Byte Count, it should emit the \ucN keyword prior to the \uN keyword to notify the reader of the change.
RTF control words generally accept signed 16-bit numbers as arguments. For this reason, Unicode values greater than 32767 must be expressed as negative number