RTF文件格式解析(一)文本编码

 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编码

你可能感兴趣的:(文档结构,c++,windows)