如何正确解码 RTF 中的十六进制值

How to Properly Decode Hex Values in RTF

不幸的是,这个有两个兔子洞,文本编码和 RTF。但它就在这里。

背景

我正在研究 NLP 文本管道,我们需要将 RTF 转换为纯文本,换句话说,我们需要删除 RTF 控制字符并保持文本内容不变。我们正在 python 中构建管道,它有几个要求阻止我们在生产中使用 Apache Tikka 之类的东西。

我知道如果文档的作者键入非 ascii 字符,RTF 可以包含 \'a9 等十六进制值。我也知道文档中的第一个控制字符序列指定了如何解码这些十六进制值,例如\ansicpg1252。例如,在这种情况下,文档开头存在 \ansicpg1252 意味着 \'a9 应根据 the windows-1252 encoding.[=36 解释为 unicode 代码点 00A9 (COPYRIGHT SIGN) =]

问题

我在第一组控制字符中遇到了一个带有 \ansicpg1252 的 RTF 文档,但是文档中有几个地方出现了以下十六进制文字 \'81\'aa。这是令人困惑的,因为 0x81windows-1252 编码中未定义。我想它可能是 utf-8,但它也没有在 utf-8 中定义。

WordPad.exe代表这两个字节用这个字符:↑

Apache Tikka 使用相同的字符,↑

这个字符对应于 unicode 代码点 2191 (Upwards Arrow),事实证明我们的神秘字节 0x81AA 是使用 Windows Code Page 932 encoding 编码这个字符的结果,其中包含日语字符。

作为参考,RTF 文档中这两个字节的完整上下文是

\plain\f1\fs20 \'81\'aa\plain\f0\fs20

并且文档在 \fonttbl 组中包含此条目:

{\f1\fmodern\fcharset128\fprq1 MS Mincho;}

据我所知,这意味着 \f1 之后的任何文本都应使用 MS Mincho 字体呈现,这是有道理的,因为 MS Mincho 包含日语字形。但是 RTF 解析器如何知道 0x81AA 应该使用 Windows Code Page 932 而不是文件第一行中指定的 ansicpg1252 进行解码?我需要知道某些字体暗示某些编码吗?

我最好的猜测是它与 \fonttbl 条目中 \fcharset128 的部分有关,但我不确定。

发表评论后,我做了更多挖掘...

fcharset 参数来自一组固定的值,这些值映射到所使用的编码。这是一个例子:

https://github.com/joniles/rtfparserkit/blob/master/src/main/java/com/rtfparserkit/parser/standard/FontCharset.java

根据我的记忆 认为 我从 Microsoft 的 RTF 规范文档中挑选了这些 (https://www.microsoft.com/en-us/download/details.aspx?id=10725)