PDF学习二:PDF文件物理结构

本文转载自:https://blog.csdn.net/u012632138/article/details/80565220

 

说明:

在PDF学习一 Hello World中简单提到了PDF文件结构。本文将重点讲PDF文件结构,指的是其文件物理组织方式,决定对象是如何存放在一个PDF文件中, 它们是如何被访问的,如何被更新的。

目标:

掌握PDF基本物理结构。

PDF文件物理结构

 

PDF文件格式包含以下4个部分:

文件头 Header

——指明了该文件所遵从的PDF规范的版本号,它出现在PDF文件的第一行。

%PDF−1.7

这是个固定格式,表示这个PDF文件遵循的PDF规范版本。从1.4版本以后,PDF文件的版本并不唯一的只是在这里表示了,可能后面会改写(catalog的Version词条),所以解析PDF的时候,如果这里的版本大于等于1.4,应该再比较一下catalog里面的version,取其中高一点的版本。

文件体 Body

——又称对象集合,PDF文件最重要的部分,文件中用到的所有对象,包括文本/图象/音乐/视频/字体/超连接/加密信息/文档结构信息等等,都在这里定义。

格式如下:


2 0 obj     
... 
end obj

一个对象的定义包含4个部分:

前面的2是对象序号,其用来唯一标记一个对象。0是生成号,按照PDF规范,如果一个PDF文件被修改,那这个数字是累加的,它和对象序号一起标记是原始对象还是修改后的对象,但是实际应用开发中,很少有用这种方式修改PDF的,都是重新编排对象号。obj和endobj是对象的定义范围,可以抽象的理解为这就是一个左括号和右括号;省略号部分是PDF规定的任意合法对象(一共8种)。

可以通过R关键字来引用任何一个对象,比如要引用上面的对象,可以使用2 0 R。

交叉引用表 Cross-reference table

——为了能对间接对象进行随机存取而设立的一个间接对象的地址索引表。(实际以偏移+索引的方式储存对象地址)

普通文件交叉引用表

xref                             % 表示交叉引用表开始
0 5                              % 0表示交叉引用表描述的对象编号从0开始,5表示共有5个对象
0000000000 65535 f  % 一般pdf都是以这行开始交叉引用表,起始地址0和最大产生号65535,f 表示释放
0000000017 00000 n % 对象号为1的偏移地址,产生号0,n表示在使用中
0000000081 00000 n % 对象号为2的偏移地址,产生号0,n表示在使用中,其他类同
0000000331 00000 n
0000000409 00000 n

增量更新的交叉引用表

xref
0 1
0000000000 65535 f
3 1                              % 对象编号从3开始,1表示共有1个对象
0000025325 00000 n % 对象号为3的偏移地址,产生号0,n表示在使用中
23 2
0000025518 00002 n % 对象号为23的偏移地址,产生号为2表示被删除过,又重新开始使用,n表示在使用中
0000025635 00000 n
30 1
0000025777 00000 n

文件尾 Trailer

——声明了交叉引用表的地址,即指明了文件体的根对象(Catalog),从而能够找到PDF文件中各个对象体的位置,达到随机访问。另外还保存了PDF文件的加密等安全信息。

trailer              % 文件尾标识,是小写t
<</Info 1 0 R  % 文件信息字典,包含Title、Author、Subject、Keywords等信息

/Root 2 0 R    % 指向文件体的根对象(Catalog)

/Size 20>>     % 文件中对象总数为20
startxref 
2559              % 交叉引用表偏移地址
%%EOF        % 文件结束标识

增量更新

1)PDF文件内容可以增量更新无需重写整篇文件。变化数据被附加到文件尾段,保持原内容不变。用这种方法更新文件最大的优势是一个篇幅很大的文件做小改动可以快速保存。

2)文件更新时新增的交叉引用表部分仅包含那些已经被修改,替换,或删掉的对象。删除掉的对象原封不动的留在文件中,对应的交叉引用表项被标记为已删除。新增的文件尾包括所有的选项(可能是改进过的)包括之前的文件尾部分,Prev项给出之前交叉引用部分的位置。一篇被更新过多次的文件包含了多个文件尾;每个文件尾都有自己的结束标识(%%EOF)。

3)由于更新的部分被添加到文件中,一个文件可能有一个相同对象的多个副本,而保持相同的对象标识(对象编号和生成编号)。在以下情况这个现象就会发生,例如,如果一个文本标注被修改多次并且文件保存了多次的修改。因为文本标注对象没删除,它仍保持着之前相同的对象号和生成号。但一个被修改过的对象副本会被包含在更新部分添加到文件中。更新的交叉引用表部分包含这个新的对象的字节偏移值,覆盖原先交叉引用表中旧的字节偏移值。当一个用户应用程序(consumer application FoxitReader)读取文件时,它必需用这种方法构建它自己的交叉引用表信息,即文件中每个对象的最新副本是被访问的那一个。

PDF 1.4之后,版本号Version是可以在增量更新中修改。

增量更新后的文档结构

后记:

PDF物理结构中还有Object Streams、Cross-Reference Streams,大家对哪个感兴趣可留言给我。

问题汇总:

Q: 一个PDF文件可以有多个文件尾吗?

A:是的。增量更新之后PDF文件会有多个文件体,多个交叉引用表,多个文件尾。

 

上一篇: https://blog.csdn.net/lzfly/article/details/80506332

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页