pdf文档解析
最近看了個開源項目代碼xpdf,從pdf文檔中提取文本,用于建全文索引,老外的代碼什么都好,就是對中文支持不好,估計也是GNU標準惹的禍,但愿以后unicode橫行的時候,我們這些chinese coder會過得更輕松一點。?
 沒辦法,只能自己看Adobe的官方資料?鏈接地址?,研究一下pdf的協議標準,下面是一片介紹pdf文檔架構的文章。
 
Adobe的PDF參考告訴我們一個PDF文件可以通過下面4個方面來理解:??
 1.??對象?, 一個PDF文檔是由一個由基本數據類型組成的數據結構。??
 2.??文件?(物理結構), 決定對象是如何存放在一個PDF文件中的, 它們是如何被訪問的,如何被更新的。這個結構是獨立于對象的語義的。?
 3.??文檔結構?, 說明一些基本的對象類型是如何來表現PDF文檔的成分的:頁,字體,批注,和另外一些內容。??
 4.??內容流?.一個PDF文件內容流包含一系列的指令,描述頁面的外觀或其他圖形實體的外觀和文件內容。??
 但是當時對我來說要看懂這幾行字是有很大的困難的,需要了解確切含義,必須看完后面的幾十頁上百頁的內容并且要分析一下一個實際的PDF文件才能完全領會它的意思。??
 后來經過長時間的文檔閱讀,相關開發,并且具體地分析PDF文件后才把PDF文件的語法,文件的解析搞清楚。雖然說學習是痛并快樂著,但是對于當時我來說真的希望有一個人能夠告訴我一個簡單的例子,通過一個簡單的例子來描述PDF的基本組成,它的解析原理和過程。因此下面我主要將以一個簡單的例子來說明PDF的主要特性并給出一個簡單的PDF文件的全景。??
 
 
1.PDF格式和HTML,XML格式:??
一個PDF文檔從根本上來說是一個8字節序。其實PDF格式和我們已經熟知的HTML,XML等結構化的文件格式一樣,包含有關鍵字,分隔符,數據等等。? ?不同的是PDF文件是按照二進制流的方式保存的,而html文件則是文本方式保存的。XML文件一般只包含數據本身,并沒有把如何顯示的信息放在其中,因此要顯示一個XML文件還需要一個Schema文件才能顯示,否則看到的將是所有的字節流;HTML包含了數據的同時也包含了一些關于如何顯示的信息,但是HTML是基于文本存放的,是可讀的,你打開一個HTML文件就能知道所有顯示在瀏覽器里得文字。 另外就是HTML不能包含二進制流,它對圖像文件的引用都是通過鏈接的,全部是外部文件的方式來實現的。? ?
2.PDF規范的發展??
PDF規范從1993年到現在,已經有過7個版本,六次版本升級,從最初的pdf1.0.6版本到現在的PDF1.7, 每次的版本升級都會加入一些新的特性,PDF參考說明書也是從最初的100多頁到現在的1000多頁,但是PDF文件格式的主要特性還是沒有改變,可以這么理解,PDF1.6是PDF1.0的擴展集,學習了PDF1.0以后也能基本上理解PDF1.6的內容。 因此說我下面的例子是基于一個PDF1.0的最簡單的一個PDF文件的分析。? ?PDF規范的發展升級:
1.1 1995 加入了文檔加密(40字節),線索樹,名字樹,鏈接,設備獨立色彩資源。? ?
1.2 1996 表單, 半色調屏幕,和其他的一些高級色彩特性, 對中文,日文和韓文的支持? ?
1.3 2000 數字簽名, 邏輯結構, JavaScript, 嵌入式文件,Masked Images, 平滑陰影, 支持 CID字體的附加色彩。? ?
1.4 2001 文件加密 (128 字節), 標簽式 PDF, 訪問控制,透明,元數據流? ?
1.5 2003 文檔加密 (公鑰), JPEG 2000 壓縮, 可選的內容組,附加的注解類型? ?
1.6 2005 文檔加密 (AES),增加最大文件支持,加入3D支持,額外的注解類型? ?
1.7?
3.PDF文件的基本組成:??
一個PDF文件從大的方面來說分4個部分:? ?l 文件頭,指明了該文件所遵從的PDF規范的版本號,它出現在PDF文件的第一行。? ?
l 文件體,PDF文件的主要部分,由一系列對象組成。? ?
l 交叉引用表,為了能對間接對象進行隨機存取而設立的一個間接對象的地址索引表。? ?
l 文件尾,聲明了交叉引用表的地址,即指明了文件體的根對象(Catalog),從而能夠找到PDF文件中各個對象體的位置,達到隨機訪問。另外還保存了PDF文件的加密等安全信息(以后詳細討論)。? ?
如下圖:
 
 
4.PDF文檔的邏輯結構?
作為一種結構化的文件格式,一個PDF文檔是由一些稱為“對象”的模塊組成的。并且每個對象都有數字標號,這樣的話可以這些對象就可以北其他的對象所引用。這些對象不需要按照順序出現在PDF文檔里面,出現的順序可以是任意的,比如一個PDF文件有3頁,第3頁可以出現在第一頁以前,對象按照順序出現唯一的好處就是能夠增加文件的可讀性,如果你不會用文本編輯器來閱讀PDF結構,那么大可不必關心。正是因為頁與頁之間的不相關性,就可以對PDF文件的頁碼進行隨機的訪問。?文件尾(Trail),說明根對象的對象號,并且說明交叉引用表的位置,通過對交叉引用表的查詢可以目錄對象(Catalog)。這個目錄對象是該PDF文檔的根對象,包含PDF文檔的大綱(outline)和頁面組對象(pages)引用。大綱對象是指PDF文件的書簽樹;頁面組對象(pages)包含該文件的頁面數,各個頁面對象(page)的對象號。?
一個PDF文檔有下圖所示的層次關系:
頁面(page)對象作為PDF中最重要的對象,包含如何顯示該頁面的信息,例如使用的字體,包含的內容(文字,圖片等),頁面的大小。當然里面的子項也可以是其他對象的引用。頁面中包含的信息是包含在一個稱為流(stream)的對象里,這個流的長度(字節數)必須直接給出或指向另外一個對象。如下圖:
5. PDF的基本語法:?
文件的第一行是文件頭,指明了該文件所遵從的PDF規范的版本號,它出現在PDF文件的第一行。?一個對象的第一行一般有兩個數字和關鍵字“obj”。例如:?
3 0 obj << /Type /Pages /Count 1 /Kids [4 0 R] >> endobj 第一個數字稱為對象號,來唯一標識一個對象的,第二個是產生號,是來表明它在被創建后的第幾次修改,所有新創建的PDF文件的對象號應該都是0,即第一次被創建以后沒有被修改過。上面的例子就說明該對象的對象號是3,而且創建后沒有被修改過。?
對象的內容應該是包含在<< 和>>之間的,最后以關鍵字endobj結束.?
6. 文件Hello World的文件分析:?
6.1.文件的具體分析
%PDF-1.0?文件頭,說明符合PDF1.0規范?
1 0 obj << /Type /Catalog /Pages 3 0 R /Outlines 2 0 R >> endobjCatalog對象(根對象)?
2 0 obj << /Type /Outlines /Count 0 >> endobjoutline對象(此處它的計數為0,說明沒有書簽)?
3 0 obj << /Type /Pages /Count 1 /Kids [4 0 R] >> endobjpages對象(頁面組對象),/Type /Pages 說明自身的屬性,對象的類型為頁碼,/Count 1說明頁碼數量為1,/Kids [4 0 R]說明頁的對象為4, 這里要說明的是如果有多個頁面,就多個頁面直接連續下去,比如說/Kids [4 0 R 10 0 R], 就說明該PDF的第一頁的對象號是4,第二頁的對象號是10。?
4 0 obj << /Type /Page /Parent 3 0 R /Resources << /Font << /F1 7 0 R >> /ProcSet 6 0 R >> /MediaBox [0 0 612 792] /Contents 5 0 R >> endobj頁對象,/Parent 3 0 R說明其父對象的對象號為3,/Resources << /Font << /F1 7 0 R >> /ProcSet 6 0 R >>說明該頁所要包含的資源,包括字體和內容的類型,/MediaBox [0 0 612 792]說明頁面的顯示大小(以象素為單位),/Contents 5 0 R說明頁面內容對象的對象號為5。?
5 0 obj << /Length 44 >> stream BT /F1 24 Tf 100 100 Td (Hello World) Tj ET endstream endobj<< /Length 44 >>說明stream對象為字節數,從BT開始,ET結束,包括中間的行結束符。?
Stream說明一個流對象的開始。?
BT說明一個文字對象的開始。?
/F1 24 Tf,Tf說明True font對象,字體明為F1, 大小為24個象素。?
100 150 Td (Hello World) Tj,100 100 說明這一行文字放置的位置,對于Td, 我們可以這樣理解,我們的當前X,Y坐標分別加上100和150就是文本的位置,因為在該例子中只有一個對象,那么它的位置就是(100,150), 如果下個對象位置信息為100, 50 Td, 那么它的位置應該就是(100+100, 150+50)也就是(200,200)。(Hello World) Tj說明文本的內容,當然,如果這里是文本的內容可以寫成16進制,用<>包含。?
ET說明文字對象的結束?
endstream流對象的結束?
6 0 obj [/PDF /Text] Endobj
[/PDF /Text]說明PDF的內容類型僅僅為文本,如果有圖片則為[/PDF /Image]?
7 0 obj << /Type /Font /Subtype /Type1 /Name /F1 /BaseFont /Helvetica >> endobjObject six defines the?字體對象,不再多作解釋。?
所有的對象之后是下面的交叉引用表:?
xref 0 8 0000000000 65535 f 0000000009 00000 n 0000000074 00000 n 0000000120 00000 n 0000000179 00000 n 0000000322 00000 n 0000000415 00000 n 0000000445 00000 nxref說明一個交叉引用表的開始,交叉引用表的第一行0 8 說明下面各行所描述的對象號是從0開始,并且有8個對象。?
0000000000 65535 f,一般每個PDF文件都是以這一行開始交叉應用表的,說明對象0的起始地址為0000000000,產生號(generation number)為65535,也是最大產生號,不可以再進行更改,而且最后對象的表示是f,表明該對象為free, 這里,大家可以看到,其實這個對象可以看作是文件頭。?
0000000009 00000 n就是表示對象1,也就是catalog對象了,0000000009是其偏移地址,00000為5位產生號(最大為65535),0表明該對象未被修改過, n表示該對象在使用,區別與自由對象,不可以更改。?
下面的幾行相信大家就可以告訴我含義了。?
Trailer << /Size 8 /Root 1 0 R >> startxref 553 %%EOF trailer說明文件尾trailer對象的開始。?
/Size 8說明該PDF文件的對象數目。?
/Root 1 0 R說明根對象的對象號為1。?
Startxref?
553說明交叉引用表的偏移地址,從而可以找到PDF文檔中所有的對象的相對地址,進而訪問對象。?
%%EOF為文件結束標志。?
6.2.PDF解析過程
7.結束語:?
到這里,我們對一個最簡單的PDF文件的介紹就結束了,我想大家對PDF文件的格式和特定應該已經有所了解了。?當然,我這里介紹的是不完整的,完整的信息,請訪問adobe的網站下載:?
http://partners.adobe.com/public/developer/pdf/index_reference.html
總結
 
                            
                        - 上一篇: 如何关闭mac的SIP
- 下一篇: M2Det 网络解读
