文章目录索引数组 (/Index) 是什么有什么意义一、基本格式二、为什么需要索引数组三、具体例子场景PDF 中只有对象 0,1,5,6,7,100 存在对象 2,3,4,8-99 都不存在或空闲二进制布局示例W[1,4,1]四、在 PDFium 代码中的使用五、索引数组的意义总结索引数组 (/Index) 是什么有什么意义在 PDF 的XRef 流V5 格式中/Index数组用于定义流中包含了哪些对象号的条目。它的作用类似于传统 XRef 表中的“子节”subsection允许不连续的对象号范围被紧凑地存储在一个流中。一、基本格式/Index [ start1 count1 start2 count2 ... ]每两个整数为一组(起始对象号, 对象个数)表示从start1开始的连续count1个对象然后从start2开始的连续count2个对象依此类推。如果省略/Index则默认值为[0 Size]即包含所有对象 0 到 Size-1。二、为什么需要索引数组PDF 中的对象号可以不连续例如对象 1, 2, 5, 100 存在对象 3,4,6-99 不存在或空闲。如果强制把所有对象包括大量空闲对象的条目都放进流中会浪费大量空间。/Index允许只存储实际存在的对象范围跳过那些没有条目的对象号。类比一本 1000 页的书如果只有第 1,2,5,100 页有内容那么目录只需要列出这四页的页码而不是列出所有 1000 页即使大部分是空白。/Index就是这个“目录”。三、具体例子场景PDF 中只有对象 0,1,5,6,7,100 存在对象 2,3,4,8-99 都不存在或空闲传统 XRef 表V4需要三个子节0 2 ← 对象0-1 5 3 ← 对象5-7 100 1 ← 对象100XRef 流用/Index表示完全相同的信息/Index [0 2 5 3 100 1]流中只会包含231 6 个条目而不是 101 个条目。二进制布局示例W[1,4,1]流中条目顺序 条目0: 对象0的数据 条目1: 对象1的数据 条目2: 对象5的数据 条目3: 对象6的数据 条目4: 对象7的数据 条目5: 对象100的数据解析器根据/Index知道前 2 个条目对应对象 0 和 1接着 3 个条目对应对象 5、6、7最后 1 个条目对应对象 100四、在 PDFium 代码中的使用std::vectorstd::pairint32_t,int32_tarrIndex;CPDF_Array*pArraypDict-GetArrayFor(Index);if(pArray){for(size_t i0;ipArray-GetCount()/2;i){intstartpArray-GetIntegerAt(i*2);intcountpArray-GetIntegerAt(i*21);arrIndex.push_back({start,count});}}if(arrIndex.empty())arrIndex.push_back({0,size});// 默认覆盖所有对象随后解析时遍历arrIndex对于每一段(start, count)连续解析count个条目分别赋予对象号start, start1, ..., startcount-1。uint32_tsegindex0;// 已处理的条目总数for(autoseg:arrIndex){intstartnumseg.first;intcountseg.second;// 从流中 segindex 位置开始读取 count 个条目for(intj0;jcount;j){uint32_tobjnumstartnumj;// 解析当前条目 ...}segindexcount;}五、索引数组的意义总结作用说明节省空间只存储实际存在的对象跳过空闲对象号支持稀疏对象号允许对象号不连续如 1, 1000, 1000000与 V4 子节兼容语义相同只是表示方式从 ASCII 文本变为数组加速解析解析器直接知道每个对象号对应的条目位置无需猜测直观图示PDF 中的对象号空间0~9 0 1 2 3 4 5 6 7 8 9 ● ● ○ ○ ○ ● ● ○ ○ ● (● 存在○ 空闲) /Index [0 2, 5 2, 9 1] → 流中只有 2215 个条目 流条目顺序 [obj0] [obj1] [obj5] [obj6] [obj9]如果没有/Index就必须为对象 2,3,4,7,8 也存储条目即使它们空闲浪费空间。