实际一个PDF文件是很复杂的,了解PDF文件的物理结构,就可以提取出一个一个的对象了;PDF中的数据类型有8种:
1、booleam
用关键字true或false表示,可以是array对象的一个元素,或dictionary对象的一个条目.也可以用在PostScript计算函数里面,做为if或ifesle的一个条件。
2、numeric
包括整形和实型,不支持非十进制数字,不支持指数形式的数字.
例:
1. 整数 123 4567 +111 -2
范围:正2的31次方-1到负的2的31次方
2. 实数 12.3 0.8 +6.3 -4.01 -3. +.03
范围:±3.403×10的38次方 至 ±1.175×10的-38次方
注意:如果整数超过表示范围将转化成实数,如果实数超过范围就出错了
3、string
由一系列0-255之间的字节组成,一个string总长度不能超过65535.string有以下两种方式:
直接字串
由()包含起来的一个字串,中间可以使用转义符"/";
(abc) 表示abc
(a//) 表示a/
转义符的定义如下:
转义字符 | 含义 |
---|---|
/n | 换行 |
/r | 回车 |
/t | 水平制表符 |
/b | 退格 |
/f | 换页(Form feed (FF)) |
/( | 左括号 |
/) | 右括号 |
// | 反斜杠 |
/ddd | 八进制形式的字符 |
十六进制字串
由<>包含起来的一个16进制串,两位表示一个字,不足两位用0补齐
<Aabb> 表示AA和BB两个字符
<AAB> 表示AA和B0两个字符
4、name
由一个前导/和后面一系列字符组成,最大长度为127;和string不同的是,name是不可分割的和唯一的,不可分割就是说一个name对象就是一个原子,比如/name,不能说n就是这个name的一个元素;唯一就是指两个相同的name一定代表同一个对象;从pdf1.2开始,除了ACSII编码“0”外,其他的ACSII编码都可以用一个#加两个十六进制的数字表示
/name 表示name
/name#20is 表示name is
/name#200 表示name 0
5、array
用[]包含的一组对象,可以是任何PDF对象(包括array);虽然PDG只支持一维array,但可以通过array的嵌套实现任意维数的array(但是一个array的元素个数不能超过8191)
[549 3.14 false (Ralph) /SomeName [1 2 3]]
6、dictionary
用"<<“和”>>"包含的若干组条目,每组条目都由key和value组成,其中key必须是name对象,并且一个dictionary内的key必须是唯一的,value可以是任何PDF的合法对象(包括dictionary对象)
<</IntegerItem 12
/StringItem (a string)
/Subdictionary
<</Item1 0.4/Item2 true/LastItem (not!)/VeryLastItem (OK)>>
>>
7、stream
由一个字典,和紧跟其后面的一组关键字stream和endstream以及这组关键字中间包含一系列字节组成;内容和string很相似,但有区别在于,stream可以分几次读取,分开使用不同的部分,string必须作为一个整体一次全部读取使用,string有长度限制,但stream却没有这个限制,一般较大的数据都用stream表示;
需要注意的是,Stream必须是间接对象,并且stream的字典必须是直接对象。从1.2规范以后,stream可以以外部文件形式存在,这种情况下,解析PDF的时候stream和endstream之间的内容就被忽略掉。
dictionary
stream
… data …
endstream
字典相关属性描述参考“PDF文件结构”中的“数据流相关属性描述”;
8、NULL
用null表示,代表空;如果一个key的值为null,则这个key可以被忽略;如果引用一个不存在的object则等价于引用一个空对象
划分规则
以上八种对象是按照对象内涵来分的,如果按照对象的使用规则来说,对象又分为间接对象和直接对象。间接对象是PDF中最常用的对象,如前面对象集合里面的,所有对象都是间接对象,在其他位置通过R关键字来引用,在交叉引用表里面都是通过间接对象来引用的。直接对象就更好理解了,上面的8种对象单独出现的时候就叫直接对象。