PDF 文件结构详解与示例
一、PDF 文件的核心结构
PDF(Portable Document Format,便携文档格式)是跨平台结构化二进制格式,核心目标是 “保持文档原始排版不变”,其结构由顶层四大组件和内容层级体系构成,解析器按固定逻辑读取。
(一)顶层结构:解析器的 “导航地图”
graph LR;
A(文件头 Header)-->B(文件体 Body);
B-->C(交叉引用表 XRef);
C-->D(文件尾 Trailer);
D-->E(EOF标记);
1. 文件头(Header):身份标识
-
作用:声明 PDF 版本、区分文本文件,避免解析器误判。
-
格式:首行
%PDF-版本号(如%PDF-1.7,主流版本 1.7/2.0),后接 1-4 个非 ASCII 字符(如%âãÏÓ)验证二进制解析支持。 -
版本兼容性:高版本(如 1.7)可能含低版本(如 1.5)不支持特性(如透明图层),解析器依版本启用兼容模式。
2. 文件体(Body):内容核心
存储所有文档内容(文本、图像、字体等),最小单元为 “对象”,结构 =“多个对象 + 自由对象链表”。
(1)对象分类:间接对象与直接对象
| 类型 | 定义 | 结构特征 | 用途 |
|---|---|---|---|
| 间接对象 | 可全局引用的独立对象 | 对象号 生成号 obj ... endobj | 存储页面、字体等核心资源 |
| 直接对象 | 嵌入其他对象,不可单独引用 | 无固定标记,直接作为值存在 | 字典键值、数组元素(如页面大小) |
- 间接对象示例(页面对象):
3 0 obj % 对象号=3,生成号=0(未修改)
<< /Type /Page % 类型为“页面”
  /Parent 2 0 R % 引用对象2(Pages节点)
  /MediaBox \[0 0 612 792] % A4尺寸(8.5×11英寸,1英寸=72点)
  /Contents 4 0 R % 引用对象4(内容流)
  /Resources << /Font << /F1 5 0 R >> >> % 引用对象5(字体)
\>>
endobj
注:2 0 R为间接引用格式(对象号 生成号 R,R=Reference)。
(2)核心对象类型(8 种)
| 对象类型 | 格式示例 | 用途说明 |
|---|---|---|
| 字典(Dict) | << /Key1 Value1 /Key2 Value2 >> | 存储结构化数据(页面属性、资源列表) |
| 数组(Array) | [1 2 3 /Name (String)] | 存储有序集合(页面列表、坐标) |
| 流(Stream) | << /Length 100 >> stream ... endstream | 存储二进制数据(图像、字体) |
| 字符串(String) | (Hello PDF) 或 <48656C6C6F> | 存储文本(括号明文,尖括号十六进制) |
| 名称(Name) | /Type 或 /Font | 标识字典键(/ 开头,区分大小写) |
| 数字(Number) | 123 或 -45.6 | 存储数值(坐标、字体大小) |
| 布尔值(Boolean) | true 或 false | 存储逻辑值(是否显示注释) |
| 空值(Null) | null | 表示无值(未定义资源) |
- 流对象特殊说明:需与字典配合,字典含
/Length(流字节数)和/Filter(压缩算法,如/FlateDecode)。
3. 交叉引用表(XRef):快速定位工具
记录所有间接对象的 “文件偏移量”(字节位置),避免解析器逐行扫描,格式如下:
xref
0 6 % 段1:起始对象号=0,条目数=6(对象0\~5)
0000000000 65535 f % 对象0:偏移0,生成号65535,f=自由对象
0000000010 00000 n % 对象1:偏移10,生成号0,n=已使用对象
-
对象号 0:特殊条目,指向自由对象链表,供修改时复用。
-
偏移量:对象在文件中的字节位置,解析器可直接跳转。
4. 文件尾(Trailer)与 EOF 标记:解析入口
解析器优先读取文件末尾的 EOF 标记,再通过 Trailer 找到核心信息。
- Trailer 格式:
trailer
<< /Size 6 % XRef总条目数
  /Root 1 0 R % 文档根对象(Catalog)引用
  /Info 6 0 R % 元数据引用(可选)
  /Encrypt null % 加密信息(null=未加密,可选)
\>>
startxref
512 % XRef偏移量(文件中XRef的字节位置)
%%EOF % EOF标记(必选,缺失则文件损坏)
- 核心关键字:
/Size(XRef 条目数)、/Root(Catalog 引用,内容入口)、/Encrypt(加密开关)。
(二)内容层级结构:从根到页面
解析器通过 Trailer 找到/Root(Catalog)后,按Catalog → Pages Tree → Page → Contents/Resources读取内容,高效管理页面。
1. 文档目录(Catalog):内容总入口
字典对象,含所有顶级内容引用,核心关键字:
| 关键字 | 用途 | 示例值 |
|---|---|---|
/Type | 声明类型为 Catalog | /Catalog |
/Pages | 指向 Pages Tree 根节点 | 2 0 R |
/Outlines | 指向文档大纲(可选) | 7 0 R |
/AcroForm | 指向表单(可选) | 8 0 R |
2. 页面树(Pages Tree):页面管理体系
树形结构(Pages节点→Page节点),高效处理多页面:
- Pages 节点:页面组,含子 Pages/Page 节点,关键字
/Kids(子节点列表)、/Count(子节点总数),示例:
2 0 obj
<< /Type /Pages
  /Kids \[3 0 R 10 0 R] % 2个子Page节点(对象3、10)
  /Count 2 % 总页数2
\>>
endobj
-
Page 节点:具体页面,含大小、内容流、资源(见前文间接对象示例)。
-
优势:插入 / 删除页面仅修改
/Kids列表,无需移动所有页面对象。
3. 页面内容(Contents):文本与图形指令
Page 节点的/Contents指向内容流(Stream 对象),含 PostScript 风格指令,示例(文本绘制):
4 0 obj
<< /Length 128 /Filter /FlateDecode >>
stream
BT % 开始文本模式(Begin Text)
/F1 12 Tf % 字体F1,字号12
100 700 Td % 文本位置(X=100,Y=700,左下角为原点)
(Hello, PDF!) Tj % 绘制文本(Tj=Text Show)
ET % 结束文本模式
endstream
endobj
- 指令规则:操作数 + 运算符(如
12 Tf,12 = 操作数,Tf = 运算符)。
4. 页面资源(Resources):依赖 “素材库”
Page 节点的/Resources字典存储字体、图像等资源,避免重复,示例:
<< /Font << /F1 5 0 R >> % 字体F1引用对象5
  /XObject << /Img1 11 0 R >> % 图像Img1引用对象11
\>>
-
字体资源:存储字体描述和字形数据,确保跨平台一致(如
TrueTypeFont含/FontFile2)。 -
图像资源:
XObject形式,含尺寸(/Width//Height)、压缩算法(如 JPEG 用/DCTDecode)。
(三)PDF 关键特性与结构关联
-
跨平台兼容性:依赖 “资源内嵌” 和 “设备无关坐标系”(点为单位,1 点 = 1/72 英寸)。
-
增量更新:修改时追加新对象、XRef 段和 Trailer,旧对象标记为自由,体积可能增大。
-
损坏修复:XRef/Trailer 损坏时,工具可扫描
obj/endobj重建,核心是找到 Catalog 和 Pages 节点。 -
加密保护:
/Encrypt字典存储算法(如 AES-256)和权限(禁止打印 / 修改),解密后可读内容。
二、简单 PDF 文件结构示例与拆解
以下为合法极简 PDF 示例,可保存为.pdf文件直接打开,结构完整且适合打印参考。
(一)完整示例代码
%PDF-1.7
%âãÏÓ
% 对象1:文档信息字典
1 0 obj
<< /Title (Simple PDF Example) /Author (PDF Learner) /CreationDate (D:20240501120000+08'00') >>
endobj
% 对象2:Pages节点(页面树父节点)
2 0 obj
<< /Type /Pages /Count 1 /Kids \[3 0 R] >>
endobj
% 对象3:Page节点(第1页)
3 0 obj
<< /Type /Page /Parent 2 0 R /MediaBox \[0 0 612 792]
  /Resources << /Font << /F1 << /Type /Font /Subtype /Type1 /BaseFont /Helvetica >> >> >>
  /Contents 5 0 R >>
endobj
% 对象4:内容流长度字典
4 0 obj
<< /Length 88 >>
endobj
% 对象5:内容流(绘制文本)
5 0 obj
<< /Filter /FlateDecode /Length 4 0 R >>
stream
1 0 0 1 100 600 cm /F1 24 Tf (Hello, Simple PDF!) Tj
endstream
endobj
% 交叉引用表
xref
0 6
0000000000 65535 f
0000000015 00000 n
0000000173 00000 n
0000000279 00000 n
0000000625 00000 n
0000000666 00000 n
% 文件尾与EOF
trailer
<< /Size 6 /Root 2 0 R /Info 1 0 R >>
startxref
786
%%EOF
(二)示例结构拆解
| 组成部分 | 核心作用 | 示例关键内容 |
|---|---|---|
| 文件头 | 声明版本 + 校验,识别 PDF 文件 | %PDF-1.7 + %âãÏÓ |
| 文件体 | 存储对象(元数据、页面树、页面、资源、内容流) | 5 个对象:信息字典(1)、Pages 节点(2)、Page 节点(3)、长度字典(4)、内容流(5) |
| 交叉引用表 | 记录对象偏移量,快速定位 | xref下条目(如对象 1 偏移 15 字节,对象 5 偏移 666 字节) |
| 文件尾 | 定义解析入口(根对象) | Root 2 0 R(加载 Pages 节点 2)、Info 1 0 R(关联元数据) |
| EOF 标记 | 标记文件结束,避免无效读取 | %%EOF(必选,无则损坏) |
(三)关键注意事项
-
对象引用格式:统一为
对象号 版本号 R(如3 0 R,版本 0 为默认)。 -
内容流匹配:
/Length需与实际内容字节数一致,否则内容损坏。 -
页面树必需:PDF 需通过
Pages→Page树形管理页面,不可直接罗列页面。
原生与扫描件
- 原生PDF是指由可编辑文档( Word、Txt等格式)创建的PDF,只要有权限是能转为可编辑文字的。
- 扫描件是通过扫描的方式把文档扫描成图片格式后保存为PDF格式,扫描PDF本质上属于图像PDF,无法直接提取其中的文字。