RTF語法
一個
RTF檔案由未格式化文本、控制字、控制符號和組組成。為了更容易的轉換,一個標準的RTF檔案應該僅包含7位ASCII碼
字元,RTF檔案沒有限制檔案的行的最大長度。(再議:maximun line length是指行的字元數還是指文檔的行數?)
An RTF file consists of unformatted text, control words, control symbols, and groups. For ease of transport, a standard RTF file can consist of only 7-bit ASCII characters. (Converters that communicate with Microsoft Word for Windows or Microsoft Word for the Macintosh should expect 8-bit characters.) There is no set maximum line length for an RTF file.
控制字是一種特殊的RTF用來標記印表機控制符的格式化命令,也是程式用來管理文檔樣式的格式化信息。(再議:措辭不好)一個控制字不能超過32個
字元,一個控制字類似以下形式:
\LetterSequence<Delimiter>
LetterSequence由小寫字母字元(a-z)組成。RTF是大小寫敏感的。
一個RTF控制字的結束由分隔設定標記,以下字元可以作為分隔設定: 一個空格。在這種情況下,空格作為關鍵字的一部分。 一個數字或
連字元(-), 意味著它是一個數字參數。這數字序列的長度由其後的一個空格或除了字母和數字的其他
字元劃定。這個參數可以是正數或者負數,它的取值範圍通常是從-32767到32767。然而,Word的取值範圍可以到達由-31680到31680。Word 允許關鍵字的小數字參數取值範圍在-2,147,483,648到2,147,483,648(特別的,\bin, \revdttm,和一些圖像屬性)。(再議:a small number of keywords不知所指,應該指這些二進制檔案吧。)一個RTF解析器應該能夠將一個隨意寫出的數字字元串轉換為一個關鍵字的合法值。如果一個數值參數緊跟著控制字,這個參數就是控制字的一部分。這時,控制字通過一個空格或非字母數字字元分隔出來,和分隔其他控制字的方式相同。 除了字母和數字的其他字元。這種情況下,此分隔
字元結束控制字,而它並不屬於控制字的一部分。如果是第一種情況,空格並不會出現在文檔中。分隔設定之後的所有字元,包括空格,將被寫入文檔。基於這個理由,你應該盡在需要的情況下使用空格,不要只是將空格用在分隔RTF代碼。RTF 檔案內容一個 RTF 檔案符合以下語法:<File>'{' <header> <document> '}' 本語法是標準的RTF語法,任何RTF查看器都應該可以正確的解釋以此語法格式寫出的RTF檔案。有必要重申的是:RTF查看器沒有必要包含所有的控制字,但它必須能夠無害的忽略它不知道(或者未使用)的控制字,並且必須能正確的略過被控制字元號標記的部分。然而,生成RTF的編輯器有可能並沒完全符合這個語法規範,同樣地,RTF查看器應該有足夠能力去處理一些細微變更的控制字。雖然如此,如果一個生成RTF的編輯器符合本規範,那么任何一個正確的RTF查看器都應該能夠完美的解釋它。
分析
RTF是一種非常流行的檔案結構,很多文字編輯器都支持它,VB等開發工具甚至還提供了Richtextbox的控制項。編寫通用工具的程式設計師應該考慮在自己的軟體中加入讀寫RTF檔案的功能,這樣就需要對RTF的結構有充分的了解。而現在最重要的信息發布手段莫過於WWW了,在編輯軟體中提供RTF到HTML的轉換也是程式設計師應該考慮的事情。儘管WORD中已經有這個功能,但不能因此就對您的顧客說:“先用我的程式存成RTF,然後再用WORD......”。下面將對RTF檔案結構分析及其套用進行討論。
結構分析
RTF的結構並不複雜,但內容繁多,本文不可能一一說明,只能從總體上討論一下(如果想閱讀詳盡的RTF文檔,則可在Internet上尋找或與筆者聯繫。)每個RTF檔案都是一個文本檔案,顯示時由RTF
閱讀器格式化。檔案開始處是{\
rtf,它作為RTF檔案的標誌是必不可少的,RTF閱讀器根據它來判斷一個檔案是否為RTF格式。然後是檔案頭和正文,檔案頭包括字型表、檔案表、顏色表等幾個數據結構,正文中的字型、表格的風格就是根據檔案頭的信息來格式化的。每個表用一對大括弧括起來,當中包含了很多用字元“\”開始的命令。例如,某個顏色表如下: {\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;} 開始時用\colortbl標明大括弧內是顏色表,接著是\red0\green0\blue0,登記了一種顏色,這種顏色的紅綠藍分量都為0。其它表依此類推。檔案頭之後是正文,正文由版面格式化命令、文字和各種特殊命令組成。其中只有特殊命令用大括弧括起來,而版面格式化命令和文字是“開放式”的,從而把文字和命令分離。檔案結束時有一個“}”,和第一個“{”對應。在整個檔案中,“}”和“{”必須一一對應。這種格式是RTF
閱讀器和轉換器算法的基礎。 RTF格式還有一個特別之處,就是有些字元在命令中有特殊的含義,所以當它們作為文本出現時需要在它們的前面加一個“\”,例如“\”本身就要表示為“\\”。事實上,這種形式在大多數程式語言中是很常見的。
算法分析
本節介紹的算法雖然是針對RTF的讀寫,但也是一般檔案過濾器通用的方法,適用於各種格式檔案之間的轉換。具體來說就是把各種檔案都轉換成一種中間格式,再根據要求進行顯示或轉換。其中有個原則是一定要遵守的:程式必須能過濾掉不認識的格式。各種檔案都有其特殊的格式,在轉換過程中不可避免會出現格式損失的現象,在算法中要考慮這種情況。對於RTF這類格式化文本檔案來說,最重要的是要正確地顯示或轉換檔案的大小、顏色、字型等風格。因此,在程式中應該用一個數據結構把這些信息存起來,這個結構就是所謂的中間格式,怎樣規定悉聽尊便。以下是其流程圖: 三、難點分析 在開發過程中我們遇到了不少問題,其中有兩個問題特別有意思。 第一個問題是中文的表示方式。在RTF中中文用命令的形式表示:“\'內碼”。內碼就是漢字機內碼。不過,請注意:RTF是文本檔案,內碼是用ASCII碼來儲存的,必須把它轉換成數字才能使用。例如,“電子與電腦”在RTF中的形式是: \'b5\'e7\'d7\'d3\'d3\'eb\'b5\'e7\'c4\'d4 第二個是圖片的問題,這也是本文的重點。RTF中圖片以兩種方式存在:第一種方式是直接嵌入,以{\pict開始;第二種方式是作為OLE對象嵌入,這時以{\object開始。當RTF處理器能直接使用OLE時,RTF檔案中提供了OLE的數據;否則,檔案中直接提供圖片的數據,以{\result開始。在使用中最常見的圖片格式是內含DIB BITMAP的元檔案(METAFILE),這種格式在SDK中沒有說明,而且在RTF中是以壓縮形式儲存的,所以在轉換時有一定困難。 四.RTF格式的擴展 最後討論一下RTF格式的擴展。RTF格式作為一個標準應該是統一的,但在某種情況下進行擴展是必要的。最明顯的例子是微軟的WORD,它有自己獨有的RTF命令。如果想使自己的軟體在技術上占有優勢,也可以通過創造新的RTF命令來實現。例如,如果你希望在軟體中支持DHTML,則可在RTF中嵌入{\dhtml或{\java之類的命令。由於RTF
閱讀器有過濾不認識命令的功能,所以這樣做不會影響RTF檔案的通用性。
學習套用
一、引言
富文本格式(RTF)規範是為了便於在應用程式之間輕鬆轉儲格式化文本和圖形的一種編碼方法。現在,用戶可以利用特定轉換軟體,在不同系統如
MS-DOS、Windows、OS/2、Macintosh和Power Macintosh的應用程式之間轉移字處理文檔。RTF規範提供一種在不同的
輸出設備、操作環境和作業系統之間交換文本和圖形的一種格式。RTF使用ANSI, PC-8, Macintosh, 或IBM PC
字元集控制文檔的表示法和格式化,包括螢幕顯示和列印。憑藉RTF規範,不同的作業系統和不同的軟體程式創建的文檔能夠在這些作業系統和應用程式之間傳遞。將一個格式化的檔案轉換為RTF檔案的軟體稱為RTF書寫器。RTF書寫器用於分離現有文本中的程式控制信息,並且生成一個包含文本和與之相關的RTF組的新檔案。將RTF檔案轉換成格式化檔案的軟體則稱為RTF閱讀器。
二、RTF基本語法
RTF檔案由
未格式化本文、控制字、控制符和組組成。RTF檔案沒有限制檔案的行的最大長度。控制字是RTF用來標記列印控制符和管理文檔信息的一種特殊格式的命令。一個控制字最長32個
字元。控制字的使用格式如下: \字母序列<分隔設定>注意:每個控制字均以一個
反斜槓\開頭。字母序列由a~z 的小寫字母組成。控制字(或者稱為關鍵字)通常應該不包含任何大寫字母。
分隔設定標記RTF控制字的結束, 可以是下列各項之一:· 一個空格,這時空格是控制字的一部份。· 一個數字或連字元(-), 表示跟隨的一個數值參數。該數字序列的長度由其後的一個空格或除了字母和數字的其他字元劃定。這個參數可以是正數或者負數,它的取值範圍通常是從-32767到32767。· 任何非字母和數字的其他字元。這種情況下,此分隔字元結束控制字,而它並不屬於控制字的一部分。控制符由一個反斜線\跟隨單個非字母
字元組成。例如,\~代表一個不換行空格。控制符不需要分隔設定。組由包括在({})中的文本、控制字或控制符組成。左擴符({)表示組的開始,右擴符(})表示組的結束。每個組包括文本和文本的不同屬性。RTF檔案也能同時包括字型、格式、
螢幕顏色、圖形、腳註、注釋(註解)、
檔案頭和檔案尾、摘要信息、域和書籤的組合,以及文檔、區段、段落和字元的格式屬性。如果包括字型、檔案、格式、螢幕顏色、校訂標記,以及摘要信息組、文檔格式屬性,則他們一定要在檔案的第一純文本字元之前,這些組形成RTF的檔案頭。如果包括字型組,則它應該在格式組之前。如果組未使用,可以省略。對於RTF檔案的詳細語法及關鍵字說明請參閱《Rich Text Format (RTF) Specification v1.7》,這裡不作更詳細的說明。
三、Hello World
國際慣例,一個Hello World!演示例子,內容如下:{\
rtf1\ansi\ansicpg936\deff0\deflang1033\deflangfe2052{\fonttbl{\f0\fmodern\fprq6\fcharset134 \'cb\'ce\'cc\'e5;}}{\*\generator Msftedit 5.41.21.2500;}\viewkind4\uc1\pard\lang2052\f0\fs20 Hello World!\par}該檔案分析如下(紅色):1、檔案基本屬性:{\rtf1 RTF版本\ansi
字元集\ansicpg936簡體中文\deff0默認字型0\deflang1033美國英語\deflangfe2052中國漢語2、字型表:{\fonttbl{\f0字型0\fmodern\fprq6字型間距為6\fcharset134GB2312國標碼 \'cb\'ce\'cc\'e5
宋體;}}3、生成器信息:{\*\generator Msftedit 5.41.21.2500;}4、文檔屬性:\viewkind4正常視圖\uc1單位元組\pard默認段落屬性\lang2052中國漢語\f0字型0\fs20字型大小20磅5、正文文本:Hello World!\par
段落標記}檔案結束注意:在RTF檔案中,中文等雙位元組字元採用其單位元組ASCII碼序列表示,例如文本“宋體ABC”應該表示為:\'cb\'ce\'cc\'e5ABC,這就是為什麼RTF可讀性差的原因。
四、文字的更高級表示
掌握了基本文字表述方法後,你一定會試著進一步探索文本更高級的表示方法,如下劃線、顏色、粗體、斜體等等,而這些在V1.7規範中都作了詳細描述,本文只列出部分常用關鍵字,以供參考。l 對於字型表和顏色表的說明:對於我們在文檔中使用的每一個字型和顏色,我們都必須在文檔頭的字型表和顏色表中預先定義。字型表定義的例子如下:{\fonttbl{\f0\froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f1\fswiss\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial;}{\f10\fnil\fcharset2\fprq2{\*\panose 05000000000000000000}Wingdings;}… …}我們在使用字型時,就可以直接指定字型表的一個索引,如:“\f1Happy”表示字型為Arial 的文本Happy。如果我們想加入其他字型,如“華文中宋”,那么只需要在字型表中加入該字型說明,並在需要時引用該字型索引值即可。方法為(華文中宋的ASCII串為“\'bb\'aa\'ce\'c4\'d6\'d0\'cb\'ce”):{f222\fnil\fcharset134\fprq2\'bb\'aa\'ce\'c4\'d6\'d0\'cb\'ce;},然後通過\f222來引用該字型即可。顏色表定義的例子如下:{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192; … …}顏色表中每個顏色值採用RGB格式書寫,每個顏色用分號格開,注意第一個顏色值\c0為空,表示系統默認顏色(一般為黑色)。依次為:\0、\1、\2、… …。我們在使用顏色時(如字型顏色)就可以指定某一個顏色索引值,如“\cf2Sunday”表示字型顏色為RGB(0,0,255)藍色的文字Sundy。“\cb6ABC”表示字型背景色為RGB(255,0,0)的文字“ABC”。如果我們需要加入其他顏色值,只需要在顏色表中加入顏色定義,並通過相應的索引值來引用它即可。
字元底紋語法如下:
控制字 涵義
==============================================================
\chbrdr 字元框線(每邊均有框線)。
\chshdngN 字元陰影。參數N的值文字陰影的百分比。
\chcfpatN N是背景圖案的顏色,指定文檔顏色表的一個索引。
\chcbpatN N是填充色,指定文檔顏色表的一個索引。
\chbghoriz 指定水平線文本背景圖案。
\chbgvert 指定垂直線文本背景圖案。
\chbgfdiag 指定正向對角線文本背景圖案(\\\\)。
\chbgbdiag 指定反向對角線文本背景圖案(\\\\)。
\chbgcross 指定十字線文本背景圖案。
\chbgdcross 指定對角十字線文本背景圖案。
\chbgdkhoriz 指定粗水平線文本背景圖案。
\chbgdkvert 指定粗垂直線文本背景圖案。
\chbgdkfdiag 指定粗前斜線文本背景圖案(\\\\)。
\chbgdkbdiag 指定粗後斜線文本背景圖案(////)。
\chbgdkcross 指定粗十字線文本背景圖案。
\chbgdkdcross 指定粗對角十字線文本背景圖案。
假設我們希望得到背景為水平線、字型為華文中宋(字型索引為222)、顏色為紅色(顏色索引為6)的文本“星期天”,則只需輸入:\f222\cf6\chbghoriz\'bb\'aa\'ce\'c4\'d6\'d0\'cb\'ce 即可。
字元下劃線語法如下:
控制字 涵義
=========================================================================
\ul連續的下劃線。
\ul0關閉所有下劃線。
\ulcN 下劃線顏色。(注意:大寫N表示一個索引數字,下同)
\uld 點下劃線。
\uldash 短劃下劃線。
\uldashd 點劃下劃線。
\uldashdd 雙點劃下劃線。
\uldb 雙下劃線。
\ulhwave 加重波浪下劃線。
\ulldash 長劃下劃線。\ulnone 停止所有下劃線。\ulth 粗下劃線。
\ulthd 粗點下劃線。
\ulthdash 粗短劃下劃線。
\ulthdashd 粗點劃下劃線。
\ulthdashdd 粗雙點劃下劃線。
\ulthldash 粗長劃下劃線。
\ululdbwave 雙波浪下劃線。
\ulw 字下加下劃線。
\ulwave 波浪下劃線。 下劃線語法與前面底紋的使用相同。
其他文本顯示高級屬性:
控制字 涵義
====================================================
\outl 框線。
\ outl 0關閉之。
\scaps 小體大寫字母。
\ scaps 0關閉之。
\shad 陰影。
\ shad 0關閉之。
\strike 刪除線。
\strike0關閉之。
\striked1 雙刪除線。
\striked0關閉之。
\sub 按照字型信息的下標文本和縮小點的尺寸。
\super 按照字型信息的上標文本和縮小點的尺寸。
對齊方式語法如下:
控制字 涵義
======================================================================
\qc 居中對齊。
\qkN 使用Kashida規則調整行百分比(0-低、10-中、20-高)。
\qt .用於泰文的分散對齊。
控制字 涵義
========================================================================
\cufiN 採用
字元單位的百分比的首行縮進值,用以覆蓋\fiN的設定,雖然它們可以設為相同值。
\liN 左端縮進(默認為0)。
\linN 從左至右段落的左端縮進值;如果在從右至左段落則表示右端縮進值(默認為0)。\linN定義了段前空格數。
\culiN 採用字元單位的百分比的左端
縮進值,與\linN一樣,它用以覆蓋\liN和\linN的設定,雖然它們可以設為相同值。
\rinN 從左至右段落的右端縮進值;如果在從右至左段落則表示左端縮進值(默認為0)。\rinN定義了段前空格數。
\curiN 採用
字元單位的百分比的右端縮進值,與\rinN一樣,它用以覆蓋\riN和\rinN的設定,雖然它們可以設為相同值。
\adjustright 當文檔
格線被定義時自動調整
右縮進。
文本間距語法如下:
控制字 涵義
========================================================================
\sbN 段後間隔(默認為0)。
\saN 段前間隔(默認為0)。\sbautoN 自動段前間隔:
0 段前間距取決於\sb。
1 自動段前間距(忽略\sb)。
默認為0。\saautoN 自動段後間隔:
0 段後間距取決於\sa。1 自動段後間距(忽略\sa)默認為0。
\lisbN 採用字元單位的百分比的段前間隔值,用以覆蓋\sbN的設定,雖然它們可以設為相同值。
\lisaN 採用字元單位的百分比的段後間隔值,用以覆蓋\saN的設定,雖然它們可以設為相同值。
\slN 行間距。如果沒有使用該控制字或者使用\sl0,則行間距將根據行間字元最高值自動取值。若N為一個正值,則該值將僅僅在該值大於行間
字元最高值時才使用(否則,使用字元最高值);分N是一個負值,即使在其小於行間字元最高值時,總是使用N的絕對值。\slmultN 多倍行間距。指出當前行間距是
單倍行距的倍數。該控制字只能跟在\sl後,聯合作用。0 “最小”或者是“精確”的行距1 多倍行距,相對於“單倍”行距。
五、圖片的表示方式
摸清rtf中圖片的表示頗費了一番周折,下面的分析希望能夠加速你的學習進程。一個rtf圖片數據通常直接嵌入檔案中,這些圖象可以是16進制(默認的)或2進制格式。圖象屬於目標引用,由\pict 控制字開始。如後面的例子中將描述的,\pict關鍵字應在\*\shppict引用控制關鍵字之後。
一個圖象的例子如下:
{\*\shppict{\pict
{\*\picprop\shplid1025{\sp{\sn shapetype}{\sv 75}}{\sp{\sn ffliph}{\sv 0}}{\sp{\sn fflipv}{\sv 0}}{\sp{\sn pibflags}{\sv 2}}{\sp{\sn fline}{\sv 0}}{\sp{\sn flayoutincell}{\sv 1}}}
\picscalex100\picscaley100\piccropl0\piccropr0\piccropt0\piccropb0\picw4516\pich4516\picwgoal2560\pichgoal2560\jpegblip\bliptag-728883813
{\*\blipuid d48e1d9b2268ef9f2741709749fb439c}
ffd8ffe000104a46494600010101004800480000ffdb0043000604040405040605050609060506090b080606080b0c0a0a0b0a0a0c100c0c0c0c0c0c100c0e0f… …}}
{\nonshppict {\pict \picscalex100\picscaley100\piccropl0\piccropr0\piccropt0\piccropb0\picw4516\pich4516\picwgoal2560\pichgoal2560\wmetafile8\bliptag-728883813\blipupi72
{\*\blipuid d48e1d9b2268ef9f2741709749fb439c}
0100090000034660000000002160000000000400000003010800050000000b0200000000050000000c02ac00ac00030000001e00040000000701040021600000… …}}
其分析如下(紅色):
{\*\shppict圖片(引用)
{\pict圖片開始
繪圖對象屬性(這個組可以省略):
{\*\picprop表示這裡是套用於一個內嵌圖象的形狀屬性\shplid1025標識每個圖形的唯一數值
{\sp繪圖對象屬性定義
{\sn shapetype}{\sv 75}} 圖片類型為相框
{\sp{\sn ffliph}{\sv 0}} 水平翻轉:false
{\sp{\sn fflipv}{\sv 0}} 垂直翻轉:false
{\sp{\sn pibflags}{\sv 2}} 連結圖片標誌
{\sp{\sn fline}{\sv 0}}具有線條:false
{\sp{\sn flayoutincell}{\sv 1}}允許圖形錨點定位在單元格內部:true
}繪圖對象屬性定義結束
圖片屬性:
\picscalex100水平縮放比例\picscaley100垂直縮放比例
\piccropl0左端剪下值=0\piccropr0右端剪下值=0\piccropt0上端剪下值=0\piccropb0下端剪下值=0
\picw4516圖片的像素寬度\pich4516圖片的像素高度\picwgoal2560圖象期望寬度\pichgoal2560圖象期望高度\jpegblip圖片源為一個jpeg檔案\bliptag圖象id標識-728883813
{\*\blipuid d48e1d9b2268ef9f2741709749fb439c}
圖片16進制數據:
ffd8ffe000104a46494600010101004800480000ffdb0043000604040405040605050609060506090b080606080b0c0a0a0b0a0a0c100c0c0c0c0c0c100c0e0f}16進制圖片數據結束
}
兼容性wmetafile檔案內容(可用省略):
{\nonshppict只用於兼容,不讀取
{\pict圖片開始\picscalex100\picscaley100\piccropl0\piccropr0\piccropt0\piccropb0\picw4516\pich4516\picwgoal2560\pichgoal2560\wmetafile8\bliptag-728883813\blipupi72
{\*\blipuid d48e1d9b2268ef9f2741709749fb439c}
下面是metafile類型的16進制數據:
0100090000034660000000002160000000000400000003010800050000000b0200000000050000000c02ac00ac00030000001e00040000000701040021600000
}metafile類型16進制圖片數據結束
}
為了簡化分析,我們除去所以可以省略的內容,則一副圖片可以這樣表示:
{\*\shppict{\pict piccropl0\piccropr0\piccropt0\piccropb0\picw寬度\pich高度\picwgoal顯示寬度\pichgoal顯示高度\jpegblipjpeg類型\bliptag-728883813id值(為一個負的長整形值)
下面是該圖片的實際16進制數據:
ffd8ffe0001… …}}
六、表格基本表示方法
上面對文本和圖片都進行了分析,相信你已經對rtf檔案格式有了一定體會,接下來說明rtf檔案中表的表示方法。表的定義稍顯複雜,不過還是有規律可循的。不存在rtf表組,實際上表由段落屬性來描述。一個表表現為多個表行的順序排列。一個表行是一個由不同單元格組成的段落序列。簡言之,表格由行組成,行由單元格組成。不管有多複雜的表格,它都是通過一行接一行的描述來實現的,包括表格的嵌套。表行從控制字\trowd開始,\row結束。包含在一個表行中的每個段落必須指定\intbl控制字或者從前一段落繼承。一個單元內可能有多個段落;單元由單元格標誌(\cell控制字)結束,行由行標誌(\row控制字)結束。表行也可以被絕對定位。此時,表行的每個段落必須具有相同的定位控制字。表的屬性可以從前一行繼承;因此,連續的表行可以通過單一的<tbldef>來定義。
一個簡單表格例子如下:
1,1 1,2 1,3
2,1 2,2 2,3
rtf內容如下:
\trowd \irow0\irowband0\ts15\trgaph108\trleft-108\trbrdrt
\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10
\trftswidth1\trftswidthb3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid2113686\tbllkhdrrows\tbllklastrow\tbllkhdrcols\tbllklastcol \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr
\brdrs\brdrw10 \cltxlrtb\clftswidth3\clwwidth2840\clshdrawnil \cellx2732\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftswidth3\clwwidth2841\clshdrawnil \cellx5573\clvertalt\clbrdrt
\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftswidth3\clwwidth2841\clshdrawnil \cellx8414\pard\plain \qj \li0\ri0\nowidctlpar\intbl\
aspalpha\
aspnum\faauto\adjustright\rin0\lin0\yts15
\fs21\lang1033\langfe2052\kerning2\loch\af0\hich\af0\dbch\af13\cgrid\langnp1033\langfenp2052 {\insrsid2113686 \hich\af0\dbch\af13\loch\f0 1,1\cell \hich\af0\dbch\af13\loch\f0 1,2\cell \hich\af0\dbch\af13\loch\f0 1,3\cell }\pard\plain
\ql \li0\ri0\widctlpar\intbl\aspalpha\aspnum\faauto\adjustright\rin0\lin0 \fs21\lang1033\langfe2052\kerning2\loch\af0\hich\af0\dbch\af13\cgrid\langnp1033\langfenp2052 {\insrsid2113686 \trowd \irow0\irowband0\ts15\trgaph108\trleft-108\trbrdrt
\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10
\trftswidth1\trftswidthb3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid2113686\tbllkhdrrows\tbllklastrow\tbllkhdrcols\tbllklastcol \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr
\brdrs\brdrw10 \cltxlrtb\clftswidth3\clwwidth2840\clshdrawnil \cellx2732\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftswidth3\clwwidth2841\clshdrawnil \cellx5573\clvertalt\clbrdrt
\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftswidth3\clwwidth2841\clshdrawnil \cellx8414\row }\pard\plain \qj \li0\ri0\nowidctlpar\intbl\aspalpha\aspnum\faauto\adjustright\rin0\lin0\yts15
\fs21\lang1033\langfe2052\kerning2\loch\af0\hich\af0\dbch\af13\cgrid\langnp1033\langfenp2052 {\insrsid2113686 \hich\af0\dbch\af13\loch\f0 2,1\cell \hich\af0\dbch\af13\loch\f0 2,2\cell \hich\af0\dbch\af13\loch\f0 2,3\cell }\pard\plain
\ql \li0\ri0\widctlpar\intbl\aspalpha\aspnum\faauto\adjustright\rin0\lin0 \fs21\lang1033\langfe2052\kerning2\loch\af0\hich\af0\dbch\af13\cgrid\langnp1033\langfenp2052 {\insrsid2113686 \trowd \irow1\irowband1\lastrow \ts15\trgaph108\trleft-108\trbrdrt
\brdrs\brdrw10 \trbrdrl\brdrs\brdrw10 \trbrdrb\brdrs\brdrw10 \trbrdrr\brdrs\brdrw10 \trbrdrh\brdrs\brdrw10 \trbrdrv\brdrs\brdrw10
\trftswidth1\trftswidthb3\trautofit1\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblrsid2113686\tbllkhdrrows\tbllklastrow\tbllkhdrcols\tbllklastcol \clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr
\brdrs\brdrw10 \cltxlrtb\clftswidth3\clwwidth2840\clshdrawnil \cellx2732\clvertalt\clbrdrt\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftswidth3\clwwidth2841\clshdrawnil \cellx5573\clvertalt\clbrdrt
\brdrs\brdrw10 \clbrdrl\brdrs\brdrw10 \clbrdrb\brdrs\brdrw10 \clbrdrr\brdrs\brdrw10 \cltxlrtb\clftswidth3\clwwidth2841\clshdrawnil \cellx8414\row }
是不是很複雜?不過沒關係,我們通過對其進行分段,並加入適當注釋,你就會對rtf檔案中的表結構一目了然。首先需要聲明的是,rtf1.7規範中規定,表行的格式如下:(<tbldef> <cell>+ <tbldef> \row) | (<tbldef> <cell>+ \row) | (<cell>+ <tbldef> \row),目前word2003採用的方式就是第一種,即“定義+內容+重複定義”,如此一來就會有很大的數據冗餘,這就是為什麼word2003的一個簡單文檔都會很大的原因,不過為了兼容性考慮,這樣處理也是必要的。其定義也由“行定義+單元格定義”組成,其中單元格定義可用重複。
分析代碼如下(紅色):
表格行1
\trowd表行1開始
表格屬性
\trgaph108表中單元格半間距\trleft-108表的最左邊位置
行框線設定
\trbrdrt行的上框線\brdrs單倍厚度\brdrw10線寬
\trbrdrl行的左框線\brdrs單倍厚度\brdrw10線寬
\trbrdrb行的下框線\brdrs單倍厚度\brdrw10線寬
\trbrdrr行的右框線\brdrs單倍厚度\brdrw10線寬
單元格1框線設定
\clbrdrt單元格上框線\brdrw15線寬\brdrs單倍厚度
\clbrdrl單元格左框線\brdrw15線寬\brdrs單倍厚度
\clbrdrb單元格下框線\brdrw15線寬\brdrs單倍厚度
\clbrdrr單元格右框線\brdrw15線寬\brdrs單倍厚度
\cellx2732單元格右邊界
單元格2框線設定
\clbrdrt單元格上框線\brdrw15線寬\brdrs單倍厚度
\clbrdrl單元格左框線\brdrw15線寬\brdrs單倍厚度
\clbrdrb單元格下框線\brdrw15線寬\brdrs單倍厚度
\clbrdrr單元格右框線\brdrw15線寬\brdrs單倍厚度
\cellx5573單元格右邊界
單元格3框線設定
\clbrdrt單元格上框線\brdrw15線寬\brdrs單倍厚度
\clbrdrl單元格左框線\brdrw15線寬\brdrs單倍厚度
\clbrdrb單元格下框線\brdrw15線寬\brdrs單倍厚度
\clbrdrr單元格右框線\brdrw15線寬\brdrs單倍厚度
\cellx8414單元格右邊界
行1數據
\pard重置段落屬性\intbl段落是表的一部分\kerning2緊縮字元尺寸\f0字型0\fs21尺寸21
1,1 1,1 \cell表單元格1結束
1,2 1,2 \cell表單元格2結束
1,3 1,3 \cell表單元格3結束
\f1字型1
\row表行1結束
\f0字型0
表格行2
\trowd表行2開始
\trgaph108表中單元格半間距\trleft-108表的最左邊位置
行框線設定
\trbrdrt\brdrs\brdrw10
\trbrdrl\brdrs\brdrw10
\trbrdrb\brdrs\brdrw10
\trbrdrr\brdrs\brdrw10
單元格1框線設定
\clbrdrt\brdrw15\brdrs
\clbrdrl\brdrw15\brdrs
\clbrdrb\brdrw15\brdrs
\clbrdrr\brdrw15\brdrs
\cellx2732
單元格2框線設定
\clbrdrt\brdrw15\brdrs
\clbrdrl\brdrw15\brdrs
\clbrdrb\brdrw15\brdrs
\clbrdrr\brdrw15\brdrs
\cellx5573
單元格3框線設定
\clbrdrt\brdrw15\brdrs
\clbrdrl\brdrw15\brdrs
\clbrdrb\brdrw15\brdrs
\clbrdrr\brdrw15\brdrs
\cellx8414
行2數據
\intbl 段落是表的一部分
2,1 2,1\cell表單元格1結束
2,2 2,2\cell表單元格2結束
2,3 2,3\cell表單元格3結束
\f1字型1
\row表行2結束
至此,你應該對rtf表格輸出有一定認識了吧。當然在表格中插入圖片、嵌入表格等的實現方法同理,嵌入的圖片可以等同於一段文本來處理,但是嵌套表格的實現可能比較複雜,因為它涉及段落文本嵌套層次等高級問題,這裡不再詳述,有興趣的讀者可以參考《rich text format (rtf) specification v1.7》。
七、小結
通過對rtf檔案的分析,我們得出一個rtf檔案基本結構如下:
rtf檔案<file>
檔案頭<header>
rtf版本\rtf
字元集<charset>
默認字型區域設定<deffont>
默認字型號\deff?
字型表<fonttbl>
檔案表<filetbl>?
顏色表<colortbl>?
樣式表<stylesheet>?
編目表<listtables>?
編目表{ \*\listtable }
編目替換表{ \*\listoverridetable }
段落組屬性{ \*\pgptbl }
跟蹤修訂<revtbl>?
rsid表<rsidtable>?
生成器信息<generator>?
文檔區<document>
文檔信息區<info>?
標題<title>?
主題<subject>?
作者<author>?
經理<manager>?
公司<company>?
最後修改者<operator>?
文檔類別<category>?
關鍵字<keywords>?
注釋<comment>?
文檔的版本號\version?
word摘要信息中的注釋<doccomm>?
內部版本號\vern?
創建時間<creatim>?
修訂時間<revtim>?
最後列印時間<printim>?
備份時間<buptim>?
總編輯時間(單位:分鐘)\edmins?
頁數\nofpages?
字數\nofwords?
包含空格的總字元數\nofchars?
內部id號\id?
文檔格式屬性<docfmt>*
節文本<section>+
節格式屬性<secfmt>*
頁眉頁腳設定<hdrftr>?
段落文本<para>+
文本<textpar>|
項目符號與編號<pn>?
段落框線<brdrdef>?
段落格式屬性<parfmt>*
定位對象與框線<apoctl>*
定位點設定<tabdef>?
段落底紋<shading>?
隱藏與否(/v /spv)?
表格<row>
行開始\trowd
行定義<tbldef>
單元格<cell>+
單元格定義+
單元格內容+
重複行定義<tbldef>
行結束\row
字元文本<char>+
圖片<pict>
圖片開始{\*\shppict {\pict }
圖片屬性
圖片數據
對象<obj>
繪圖對象\shp
腳註\footnote
注釋<annot>
域<field>