-
PDF(Portable
Document
Format,
便携式文档结构
)
是一种很有用的文件格式
,
其最大的特点是平台无关而且功能强大
(
支持文字
/
图象
/
表单
/
链接
/
音乐
/
视频等
).<
/p>
做
PDF
的解析,首先要熟悉
文件的物理结构和逻辑结构。
PDF
文件物理结构可分为以下几
块
:
1.
文件头
文件头是
PDF
文件的第一行
,
格式如下
:
%
这是个固定格式,
表示这个
PDF
文件遵循的
P
DF
规范版本,
目前
PDF
的生成工具,
除了
官方的
acrobat
,其他生成的以版本的居多。对于做
PDF
p>
开发来说,一个最简单的原则就是
生成
PD
F
的时候尽量符合低版本规范,
以保证大多数解析器能支持;<
/p>
解析
PDF
的时候尽量支
持高版本的规范,以保证支持大多数工具生成的
PDF
文件。
从版本以后,
PDF
文件的版本并不唯一的只是在这里表示了,
可能后面会改写
(
catalog
的
Ver
sion
词条)
,
所以解析
的时候,
如果这里的版本大于等于,
应该再比较一下
catalog
里面的
version
,取其中高一点的版本。
2.
对象集合
这是一个
PDF
文件最重要的部分,文件中用到的所有对象
,
包括文本
p>
/
图象
/
音
乐
/
视频
/
字体
/
超连接
/
加密信息
/
文档结构信息等等
,
都在这里定义。格式如下
:
2 0 obj
...
end obj
一个对象的定义包含
4
个部分:
前面的
2
是对象序号,其用来唯一标记一个对象;
0
是生成号,按照
PDF
规范,如果一<
/p>
个
PDF
文件被修改,
< br>那这个数字是累加的,
它和对象序号一起标记是原始对象还是修改后的
对象,
但是实际开发中,
很少有用这种方式修改<
/p>
PDF
的,
都是重新编排对象号;
obj
和
endobj
是对象的定义范围,
可以抽象的理解为这就是一个左括号和右括号;
< br>省略号部分是
PDF
规定
的任意
合法对象
(
一共
8
种,见后面附
A)
。
可以通过
R
关键字来引用任何一个对象,比如要引
用上面的对象,可以使用
2 0 R
,需
要主意的是,
R
关键字不仅可以引用一个已经定义的对象,<
/p>
还可以引用一个并不存在的对象,
而且效果就和引用了一个空对象
一样。
3.
交叉引用表
交叉引
用表是
PDf
文件内部一种特殊的文件组织方式,
可以很方便的根据对象
号随机访问一个对象。其格式如下
:
xref
0 1
65535
f
4 1
00000
n
8 3
00000
n
00000
n
00000
n
其中
,x
ref
是开始标志
,
表示以下为一个交
叉引用表的内容
;
每个交叉引用表又可以
分为若干个子段,
每个子段的第一行是两个数字,
第一个是对
象起始号,
后面是连续的对象
个数,接着每行是这个子段的每个
对象的具体信息——每行的前
10
个数字代表这个这个对
象相对文件头的偏移地址
,
后面的
5
位数字是生成号(用于标记
PDF
的更新信息,和对象的
生成号作用类似),最后一位
f
或
n
表示对象是否被使用
(n
表示使用
,f
表示被
删除或没有
用
)
。上面这个交叉引用表
一共有
3
个子段,分别有
1
个,
1
个,
3
个对象,第一个子段的对
象不可用,其余子段对象可用。
< br>
:
通过
tr
ailer
可以快速的找到交叉引用表的位置,进而可以精确定位每一个对
象;还可以通过它本身的字典还可以获取文件的一些全局信息(作者,关键字,标题等),
加密信息,等等。具体形式如下
:
trailer
<<
key1
value1
key2
value2
key3
value3
…
>>
startxref
553
%%EOF
trailer
< br>后面紧跟一个字典,包含若干键
-
值对。具体含义如下:
键
Size
值类型
整形数字
值说明
所有间接对象的个数。一个<
/p>
PDF
文件,如果被更新过,则会有多个
对象集合、交叉引用表、
trailer
,最后一个
trailer
的这个字段
记录了之前所有对象的
个数。这个值必须是直接对象。
Prev
整形数字
当文件有多个对象集合、<
/p>
交叉引用表和
trailer
时,
才会有这个键,
它表示前一个相对于文件头的偏移位置。这个值必须是
直接对象。
Root
字典
Catalog
字典(文件的逻辑入口点)的对象号。必须是间接对象。
文档被保护时,会有这个字段,加密字典的对象号。
存放文档信息的字典,必须是间接对象。
文件的
ID
Encrypt
字典
Info
字典
ID
数组
startxref:
后面的数字表示最后一个交叉引用表相对于文件起始位置的偏
移
量。
%%EOF
:
文件结束符
.
一个
PDF
文件,
都会有上面这样的结构
(线性化优化的
< br>PDF
例外,
这个后面单独说)
。
实际一个
pdf
文件是很复杂的
p>
,
但是上面几个部分是确定的
,
只能多不能少
.
了解了
P
DF
文件
的物理结构,就可以提取出一个一个的对象了
.PDF
中的对象有
8
种:
p>
用关键字
true
或
false
表示
,
可以是
array
对象的一个元素
,
或
dictionary
对象的
一
个条目
.
也可以用在
PostScri
pt
计算函数里面,做为
if
或
ifesle
的一个条件。
包括整
形和实型
,
不支持非十进制数字
,
p>
不支持指数形式的数字
.
例
:
1)
整数
123
4567
+111
-2
范围
:
正<
/p>
2
的
31
次方<
/p>
-1
到负的
2
的
31
次方
2)
实数
+
-3.
+.03
范围
:
±
×
10
的<
/p>
38
次
方
±
×
10
的<
/p>
-38
次方
注意
:
如果
整数超过表示范围将转化成实数
,
如果实数超过范围就出错了<
/p>
由一系列
0-255
之间的字节组成
,
一个
p>
string
总长度不能超过有以下两种方
式
:
1)
直接字串
由
()
包含起来的一个字串
,
中间可以使用转义符
例
:
(abc)
表示
abc
(a
p>
string
不同的是
,name
是不可分割的和唯一的
,
不可分割就是说一个<
/p>
name
对象就是一个原子
,
比如
/name,
不能说
n
就是这个
name
的一个元素
;
唯一就是指两个相同的
name
一定代表同一
个对象
.
从
开始
,
除了
ascii
的
0,
别的都可以用一个
#<
/p>
加两个十六进制的数字表示
.
例
:
/name
表示
name
/name#20is
表示
name is
/name#200
表示
name 0
用
[]<
/p>
包含的一组对象
,
可以是任何
对象
(
包括
array).
虽然
pdf
< br>只支持一维
array,
但可以通过
array
的嵌套实现任意维数的
array(
但是一个
array
的元素不能超过
8191)
例
:
[549
false
(Ralph)
/SomeName]
用
p>
和
包含的若干组条
目
,
每组条目都由
key
和
value
组成
,
其中
key
必须是
n
ame
对象
,
并且一个
dictionary
内的
key
是唯一的
;value
可以是任何
pdf
的合法对象
(
包括
dictionary
对象
).
例
:
<<
/IntegerItem
12
/StringItem
(a
string)
/Subdictionary
<<
/Item1
/Item2
true
/LastItem
(not!)
/VeryLastItem
(OK)
>>
>>
由一个字典,和紧跟其后面的一组
关键字
stream
和
endstre
am
以及这组关键字中
间包含一系列字节组成
< br>.
内容和
string
很相似<
/p>
,
但有区别
:stream
可以分几次读取
,
分开使用
不同的部分
,string
必须作为一个整体一次全部读取使用
;string
有长度限制
,
但
stream
却
没有
这个限制
.
一般较大的数据都用
str
eam
表示
.
需要注意的是,
Stream
必须是间接对象,
并且
stream
的字典必须是直接对象。从规范以后,
stream
可以以外部文件形式存在,这种
情况下,解析
PDF
的时候
stream
和
endstream
之间的内容就被忽略掉。<
/p>
例
:
dictionary
stream
…
data
…
endstream
stream
字典中常用的字段如下:
字段名
Length
类型
整形
值
(必须)关键字
< br>stream
和
endstream
之间的数据长
度,
endstream
之前可能会有一个多余的
EOL
标记,
这个不计算在数据的长度中。
Filter
名字
或
数组
(可选)
Stream
的编码算法名称(列表)。如果有多
个,则数组
中的编码算法列表顺序就是数据被编码的
顺序。
DecodeParms
字典
或
数组
(可选
)
一个参数字典或由参数字典组成的一个数
组,供
Filter
使用。如果仅有一个
Filter
p>
并且这个
Filter
需要参数,除非这个
Filter
的所有参数都已
经给了默
认值,否则的话
DecodeParms
必须设置给
Filter
。如果有多个
Filter
,并且任意一个
Filter
使用了非默认的参
数,
DecodeParms
必须
是个数
组,每个元素对应一个
Filter
的参数列表(如果某
个
Filter
无需参数或所有参数都有了默认值,就用
空对象代替)。
<
/p>
如果没有
Filter
需要参数,或者<
/p>
所有
Filter
的参数都有默认值,<
/p>
DecodeParms
就被
忽略了。
F
文件标识
(可选)保存
stream
数据的文件
。如果有这个字段,
stream
和
e
ndstream
就被忽略,
FFilter
< br>将会代替
Filter, FDecodeParms
将
代替
DecodeParms
。
Len
gth
字段还是表示
stream
和<
/p>
endstream
之间数据的长度,
但
是通常此刻已经没有数据了,长度是
0.
FFilter
FDecodeParms
名字
或
字典
(
可选
)
和
filter
类似,针对外部文件。
字典
或
数组
<
/p>
(
可选
)
和
p>
DecodeParams
类似,针对外部文件。
< br>
用
null
表示,代表空.如果一个
key
的值为
null
,则这个
key
可以被忽略;
如果
引用一个不存在的
object
则
等价于引用一个空对象.
例
:(
略
)
p>
以上八种对象是按照对象内涵来分的,
如果按照对象的使用规则来说
,
对象又分为间接对象
和直接对象。
间
接对象是
PDF
中最常用的对象,
如前
面对象集合里面的,
所有对象都是间接
对象,
< br>在其他位置通过
R
关键字来引用,
在交叉引用表里面都是通过间接对象来引用的。
直
接对象就更
好理解了,上面的
8
种对象单独出现的时候就叫直接对象。
p>
PDF
文件结构(二)
————逻辑结构
作者:
bobob
邮件
要解析一个
PDF
< br>文件,
首先要掌握
PDF
的物理
结构,
这是第一步。
但是这个仅仅只是
基础,更重要的是对
PDF
逻辑结构的解析。
PDF
的逻辑大体上是一个树
状结构,根节点是
catalog
字典,通过这里去解析页、目
录、链接信息等等,在这里按照
PDF
的树形结构,详
细讨论一下整个文件的逻辑框架。
一、
catalog
根节点
catalog
是整个
PDF
逻辑结构的根节点,这个可以通过
trailer
的
Root
字段定位,虽
然简单,但是相当重要,因
为这里是
PDF
文件物理结构和逻辑结构的连接点。
Catalog
字典包含的信息非常多,这里仅就最主要的几个字段做个说
明。
(
1
)
Pages
字段
这是个必须字段,是
PDF
里面所有页面的描述集合。
p>
Pages
字段本身是个字典,它
字段
p>
Type
Parent
里面又包含了一下几个主要字段:
类型
值
name
dictionar
y
array
integer
(
< br>必须
)
只能为
Pages
。
(
如果不
是
catalog
里面指定的跟节点,则必须有,并且必须是间
接对象
)
当前节点的直接父节点。
(
必须
)
一个间接对象组成的数组,节点可能是<
/p>
page
或
page
tree
。
(
必须
) page
tree
里面所包含叶子节点(
page
对象)的个数。
Kids
Count
-
-
-
-
-
-
-
-
-
上一篇:HE染色和巴氏染色法
下一篇:化学试剂英语