RTF文件可以存储任何文字,可是他们都是怎么存储在文档中呢,阅读器是怎么识别出哪些文本属于什么编码呢
1 字符集
在指定RTF版本后,你必须定义在这个文件中使用的字符集。字符集控制字必须在任何纯文本或任何表控制字之前。RTF规格说明目前支持下列字符集。
控制字 | 字符集 |
\ansi | ANSI (默认) |
\mac | Apple Macintosh |
\pc | IBM PC code page 437 |
\pca | IBM PC code page 850, used by IBM Personal System/2 (not implemented in version 1 of Microsoft Word for OS/2) |
字符集规定了RTF文本以什么样的编码存在文件内,目前版本的RTF默认是ANSI编码的,但是,如果保存汉字或者其他文字,ANSI编码就不够用了。
2 Unicode RTF
Word 2002支持Unicode。文本支持使用16位Unicode字符编码方案。因为直到这个版本(1.6版),RTF只直接支持7位字符处理,8位字符则需编码为十六进制数,所以在RTF中表达文本需要一种新的机制。这里描述的Unicode机制可以应用到任何RTF引用或主体文本。
控制字 | 涵义 |
\ansicpgN | 该关键字表示,在书写RTF文本时,用来执行Unicode向ANSI转换的ANSI代码页。N为10 进制形式的代码页。这是默认ANSI代码页运行环境的典型设置(例如,\ansicpg1252表示 美国Windows)。阅读器能可使用相同的ANSI代码页将ANSI文本转换回Unicode。 可能的取值如下: 437 United States IBM 美国IBM 708 Arabic (ASMO 708) 阿拉伯 709 Arabic (ASMO 449+, BCON V4) 阿拉伯 710 Arabic (transparent Arabic) 阿拉伯 711 Arabic (Nafitha Enhanced) 阿拉伯 720 Arabic (transparent ASMO) 阿拉伯 819 Windows 3.1 (United States and Western Europe) 美国和西欧 850 IBM multilingual IBM多种语言 852 Eastern European 东欧 860 Portuguese 葡萄牙 862 Hebrew 希伯来语 863 French Canadian 法国加拿大 864 Arabic 阿拉伯 865 Norwegian 挪威 866 Soviet Union 苏联 874 Thai 泰语 932 Japanese 日语 936 Simplified Chinese 简体中文 949 Korean 朝鲜语 950 Traditional Chinese 繁体中文 1250 Windows 3.1 (Eastern European) 东欧 1251 Windows 3.1 (Cyrillic) 斯拉夫语 1252 Western European 西欧 1253 Greek 希腊语 1254 Turkish 土耳其语 1255 Hebrew 希伯来语 1256 Arabic 阿拉伯 1257 Baltic 波罗的语 1258 Vietnamese 越南语 1361 Johab 该关键字应该放置在RTF头部分,在\ansi, \mac, \pc或\pca关键字之后。 |
\upr | 该关键字通过两个嵌入的子引用来描述一个引用,一个使用Unicode,另一个使用ANSI。 这个关键字连同\ud关键字一起操作,以提供向后的相容性。一般的语法如下: {\upr{keyword ansi_text}{\*\ud{keyword Unicode_text}}} 注意:这个引用关键字不使用\*关键字,如此来强制老的RTF阅读器选择ANSI表示法,放 弃Unicode表示法。 |
\ud | 这是使用Unicode表示的目标引用。其文本使用ANSI转换搭配\uN关键字的组合来表示在 ANSI中没有匹配的文字。 |
\uN | 这个关键字表示单个Unicode字符,它在当前ANSI代码页中没有相匹配的ANSI表示字符。 N是用十进制表示的Unicode字符的值。 该关键字后面直接跟随一个对应的ANSI字符。在这种情况下,旧版本的RTF阅读器将会忽 略\uN关键字,直接使用ANSI的表示法。当遇到这个关键字时,阅读器将会忽略随后的N 个字符,这个N对应于碰到的最后一个\ucN值。 对于全部RTF关键字,一个用于终止关键字的空格将会出现(在ANSI字符之前),而这并不 是需要跳过的字符。然而这并不太可能会出现(或者是被推荐),一个\bin关键字,及其声 明,以及随后的二进制数据,全部被认为是一个需要跳过的字符。如果在扫描可跳过数据 的时候,遇到一个RTF范围界定符(如:一个左括弧或右括弧),这个可跳过数据将被认为 是在界定符之前结束的。这样可以让一个阅读器来做一些基本的错误恢复。如果要将一个 RTF界定符包含到可跳过数据之中,就需要像在纯文本中一样,这个界定符使用相应的控 制符号来表示(如:使用反斜线\转义符)。为了对可跳过的字符进行计数,任何RTF控制字 或控制符都被认为是单个字符。 在RTF书写器遇到一个没有相匹配的ANSI字符的Unicode字符时,应该输出\uN,后面接 着是它所能操纵的最恰当的ANSI表示法。同时,如果在将Unicode字符翻译成ANSI字符 流的时候,遇到有一些字节跟当前Unicode字符字节数不同,就需要在\uN关键字之前使 用\ucN关键字,用于向阅读器通报发生的变化。 RTF控制字通常采用带符号的16位的数字作为变量。因此,大于32767的Unicode值必需 使用负数来表示。 |
\ucN | 这个关键字表示对应于一个给定的\uN Unicode字符的字节数。这个关键字可以在任何时刻 使用,它的值范围可视为字符的属性。也就是说,一个\ucN关键字,仅仅对其所跟随的文 字起作用,且是在同一个(或更深层)嵌套的左右括弧之内。在退出一个组的时候,前一个 \uc的值将会被恢复。阅读器需要维护一个堆栈,这个堆栈用于保存全部所碰到的这种字 节计数,在碰到一个\uN关键字的时候,阅读器要使用最近的一个值跳过相应数目的字符。当跳出一个指定了\uc值的RTF组时,阅读器需要回复到前一个值。如果在当前或外层范围内 没有找到\uc关键字,就会使用默认值1。 按照惯例,在一个Unicode引用上下文中(也就是说,在一个\ud引用单元内),不生成ANSI 对Unicode字符的表示。通常的,目标引用会包含一个\uc0控制序列。在退出\ud目标引用 的时候,不需要重新数值,因为作用域规则将会保证前一个值被恢复。 |
ansicpg控制字指定当前RTF文档默认非ansi编码的文字编码,当文本使用unicode编码存储时,使用u控制字,注意这里还有一个uc控制字,他在u控制字前面,表示uc后面的内容,一般情况下,阅读器碰到u的时候,会跳过相应数目的字符
3 字体表
ansicpg控制字只能表示一种类型的编码,当多种文字需要表述的时候,该怎么办呢,RTF使用了字体对每段的文字进行了描述,字体里面有fcharset控制字表示这段文字的编码;具体表示如下:
\fonttbl控制字用于标明字体表组。唯一的\fN 控制字定义了文档中可用的每一个字体,并且用来作为全篇文档中对字体的参考。
如果一个RTF文件使用默认字体,默认字体号将由 \deffN控制字指定,这个控制字必须在字体表组之前。在文件创建的时候,RTF书写器用数字参数N提供默认字体号。RTF阅读器通过字体表把这个号翻译成阅读器系统里最接近的可用字体。
以下控制字用于指定字体表中的字符集、可替换字体名、字符间距和无标记的字体名。
控制字 | 涵义 |
\fcharsetN | 指明字体表中一种字体的字符集。N值由Windows头文件定义。 0 ANSI 美国国家标准 1 Default 系统默认值 2 Symbol 符号 3 Invalid 无效 77 Mac Macintosh 128 Shift Jis 日本工业替换标准 129 Hangul 130 Johab 134 GB2312 国标码 136 Big5 BIG5码 161 Greek 希腊 162 Turkish 土耳其 163 Vietnamese 越南 177 Hebrew 希伯来 178 Arabic 阿拉伯 179 Arabic Traditional 180 Arabic user 181 Hebrew user 186 Baltic 波罗的语 204 Russian 俄语 222 Thai 泰语 238 Eastern European 东欧 254 PC 437 255 OEM |
当RTF文档内有多种编码文字,使用fcharset指定文字编码,作用范围是嵌套的左右括弧之内。
4 示例
这是一段RTF开头内容:
{\rtf1 \ansi \ansicpg936 \deff0 \stshfdbch1 \stshfloch0 \stshfhich0 \deflang2052 \deflangfe2052
{\fonttbl {\f0 \froman \fcharset0 \fprq2 {\*\panose 02020603050405020304}Times New Roman{\*\falt Times New Roman};}
{\f1 \fnil \fcharset134 \fprq0 {\*\panose 02010600030101010101}\'cb\'ce\'cc\'e5{\*\falt \'cb\'ce\'cc\'e5};}
{\f2 \fnil \fcharset2 \fprq0 {\*\panose 05000000000000000000}Wingdings{\*\falt Wingdings};}
{\f3 \fswiss \fcharset1 \fprq0 {\*\panose 020b0604020202020204}Arial{\*\falt Arial};}
{\f4 \froman \fcharset128 \fprq0 {\*\panose 02020609040205080304}MS Mincho{\*\falt MS Mincho};}
{\f5 \fmodern \fcharset134 \fprq0 {\*\panose 00000000000000000000}\'b7\'c2\'cb\'ce_GB2312{\*\falt \'b7\'c2\'cb\'ce};}
{\f6 \fnil \fcharset134 \fprq0 {\*\panose 00000000000000000000}\'b7\'bd\'d5\'fd\'d0\'a1\'b1\'ea\'cb\'ce\'bc\'f2\'cc\'e5{\*\falt \'ba\'da\'cc\'e5};}
{\f7 \fnil \fcharset134 \fprq0 {\*\panose 02010600040101010101}\'bb\'aa\'ce\'c4\'d6\'d0\'cb\'ce{\*\falt \'cb\'ce\'cc\'e5};}}
此处ansi指定默认存储方式是ansi编码,ansicpg936指定非ansi编码是cp-936编码, 表示简体中文(GB2312);在fonttbl表内,有f1到f7字体种类,f1下的fcharset134表示GB2312编码,f2下的fcharset2表示Symbol符号,f3下的fcharset1表示系统默认编码(deff0 ,ANSI),f4下fcharset128表示Shift_JIS编码(日本电脑系统常用的编码表)。
下面是一段文本内容:
{\fs23 \rtlch \ltrch \loch \af10 \hich \af10 \dbch \f4 \lang1033 \langnp1033 \langfe1033 \langfenp1033 \'90\'b6\'8aU{\uc1 \u35268 ?}{\uc1 \u21010 ?}}
此段文本引用了f4号字体(对应fcharset128 ),文本内容分为两部分:第一部分\'90\'b6\'8aU是一段f4对应的编码内容,属于日本系统编码,第二部分{\uc1 \u35268 ?}{\uc1 \u21010 ?}是用unicode编码内容,uc1表示\u35268后面的内容是一位(内容“?”,解析的时候可以跳过,至于\ucN的意义是什么,可以参考\uN的说明)
下面是另外一段文本内容:
{\fs24 \kerning0 \rtlch \ltrch \loch \af1 \hich \af1 \dbch \f1 \lang1033 \langnp1033 \langfe2052 \langfenp2052 2017\'c4\'ea10\'d4\'c229\'c8\'d5\'a1\'a1\'a1\'a1\'a1\'a1\'a1\'a1\'a1\'a1}
此段文本使用f1号字体(对应fcharset134 ),文本依然有两部分,ANSI编码的和GB2312编码,"2017","10"和"29"是ANSI编码,其余部分是GB2312编码