PDF便携式文档格式(英语:Portable Document Format,缩写:PDF)以PostScript语言图像模型为基础,是一种用独立于应用程序、硬件、操作系统的方式呈现文档的文件格式。本文主要信息来源于网络,为工作方便对PDF文件格式做简要说明,以便资料查询方便,有时间后续再针对每个组成部分做详细展开分析。
1. PDF文件构成综述
一个pdf文件主要是由4部分构成:文件头、文件体、交叉引用表、文件尾:
n 文件头:用来存储PDF版本
n 文件体:用来存储间接对象,这是构成PDF比重最大的内容
n 交叉索引表:用来保存各个间接对象在文件中的起始地址
n 文件尾:用来存储交叉索引表的起始位置,根对象(Root),加密对象(Encrypt),文档信息对象(Info)等
2. PDF文件之文件头
一般情况下,文件头,即,PDF文件的第一行,它用来定义PDF的版本,从而确定该PDF遵循的哪个版本的PDF规范。PDF版本是向下兼容的,即高版本的规范,兼容低版本的规范。目前主要的版本有:
n %PDF-1.0
n %PDF-1.1
n %PDF-1.2
n %PDF-1.3
n %PDF-1.4
n %PDF-1.5
n %PDF-1.6
n %PDF-1.7(最常见)
n %PDF-1.8(在标准文档里没有,只是遇到一些客户特殊的文件中会出现,非常少见
以上都是常见的版本号,还有一个特殊的版本,如PDF/X、PDF/E 和 PDF/A,PDF/VT等,它们在PDF文件中表现为文件头版本+OutputIntent相结合来标识版本。在Catalog字典中,存在Version属性,它的值也是PDF版本号,该版本号如果高与文件头版本号,则采用这里的版本号,否则忽略。这里的Version属性是可选的,通常是在PDF增量写的情况下用到。因为原PDF文件进过编辑后,添加或修改的内容需要遵循的版本比原本更高,而增量写的方式要求原PDF文件内容不修改,所以,通过修改catalog对象中Version,只要增量部分写入catalog对象,就可以改变PDF的版本号。
PDF文件头有些情况下,并不只保存了版本号,还可能在版本号前面加一下用户自定义的内容,用来满足用户的特殊需求。当遇到这种情况时,对文件头的读取算法就要写的灵活一点,不然取值会发生错误,同时还会影响到间接对象读取的问题。
3. PDF文件之文件体
一个PDF文件的文件体包括表示文档内容的对象。对象是文档的基本类型,表示文档的各个组成部分,如字体,页面,和实例图形。从PDF1.5开始,主干部分也可以包含对象流,每个对象流都包含一系列间接对象。
pdf文件中用到的所有对象,包括文本/图象/音乐/视频/字体/超连接/加密信息等等,格式如下:
2 0 obj ... end obj 其中省略号部分是pdf规定的任意合法对象(一共8种) 。
文件体有个根对象(catalog),该对象中保存着PDF的很多基本信息,并通过间接引用,辐射到所有的间接对象。
(下图是大概的树形状)
4. 交叉引用表(Cross-ReferenceTable)
交叉引用表包含的信息允许对文件中的间接对象进行随意访问,以便不需要阅读整个文件即可定位任何特殊对象了。(从PDF1.5开始,某些或所有的参照表信息也可以被含在参照流中。
交叉引用表是PDF文件唯一有固定格式的一部分,每个交叉引用表都从一个包含关键字xref的行开始。跟着这个行的是一个或多个参照子部分,这些分部可以以任何顺序出现。子部分的构造有益于逐步更新,因为它允许一个新的参照部分附加到PDF文件中来,而包含的选项紧紧只用于已经被附加或删除的对象。对一个从未被更新过的文件,参照部分只包含一个子部分,它的对象编号从0开始。
xref ----------------------------------参照表开始的的关键字0 5 ---------------------------------- 0(开始的对象号),5(后跟的对象个数)0000000000 65535 f 0000000009 00000 n 0000000074 00000 n 0000000120 00000 n 0000000179 00000 n 其中,xref是开始标志,表示以下为引用表内容;0 5表示从对象号为0的开始, 连续有5个对象(0,1,2,3,4),分别用5行来表示.每行的前10个数字代表这个对象相对文件头的偏移地址,后面5个数字只有当这个对象被删除的时候才有用,表示这个对象被删除后又被重新生成后的对象号最后一位f或n表示对象是否被使用(n表示使用,f表示被删除或没有用) 。
5. 文件尾(trailer)
文件尾部(trailer)如何找到交叉引用表和其他特殊对象属性:
/ Size [integer]:指定交叉引用表中的条目数(也计算更新部分中的对象)。使用的数字不应是间接参考。
/ Prev [integer]:指定从文件开头到上一个交叉引用部分的偏移量,如果有多个交叉引用部分,则使用该偏移量。该数字应该是交叉引用。
/ Root [字典]:指定文档目录对象的引用对象,它是一个特殊对象,包含指向不同类型的其他特殊对象的各种指针(稍后将详细介绍)。
/ Encrypt [dictionary]:指定文档的加密字典。
/ Info [字典]:指定文档信息字典的引用对象。
/ ID [array]:指定形成文件标识符的两个字节未加密字符串的数组。
/ XrefStm [integer]:指定从解码流中的文件开头到交叉引用流的偏移量。这仅存在于混合引用文件中,如果我们还想要打开文档,即使应用程序不支持压缩引用流,也会指定它。
例子:
trailer
/Size 22
/Root 2 0 R //指向文件目录对象
/Info 1 0 R //一些文件信息
startxref //用于制定从文件开头到交叉索引表的偏移量标识
24212 //交叉索引表的偏移量24212
%%EOF //文件尾部标识