仕様に基づいて、テスト済みで機能する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 このキーワードは、現在の ANSI コード ページに基づく同等の ANSI 表現を持たない単一の Unicode 文字を表します。N は、10 進数で表された Unicode 文字値を表します。このキーワードの直後には、ANSI 表記の同等の文字が続きます。このようにして、古い読者は \uN キーワードを無視し、ANSI 表現を適切に取得します。このキーワードが検出されると、リーダーは次の N 文字を無視する必要があります。ここで、N は検出された最後の \ucN 値に対応します。
すべての RTF キーワードと同様に、スキップする文字にカウントされないキーワード終了スペース (ANSI 文字の前) が存在する場合があります。これが発生する可能性は低い (または推奨される) ものの、\bin キーワード、その引数、およびそれに続くバイナリ データは、スキップのために 1 文字と見なされます。スキップ可能なデータのスキャン中に RTF スコープ区切り文字 (つまり、開き中かっこまたは閉じ中かっこ) が検出された場合、スキップ可能なデータは区切り文字の前で終了していると見なされます。これにより、リーダーは初歩的なエラー回復を実行できます。スキップ可能なデータに RTF 区切り文字を含めるには、プレーン テキストと同様に適切な制御記号を使用して (つまり、バックスラッシュでエスケープして) 表す必要があります。RTF 制御語またはシンボルは、スキップ可能な文字をカウントする目的で 1 文字と見なされます。
RTF ライターは、対応する ANSI 文字のない Unicode 文字に遭遇した場合、\uN に続いて管理できる最適な ANSI 表現を出力する必要があります。また、Unicode 文字が現在の Unicode Character Byte Count とは異なるバイト数を持つ ANSI 文字ストリームに変換される場合、\uN キーワードの前に \ucN キーワードを発行して、リーダーに変更を通知する必要があります。
RTF 制御ワードは通常、符号付き 16 ビット数値を引数として受け入れます。このため、32767 より大きい Unicode 値は負の数で表す必要があります。