MS-PPT 二进制文件格式由 Microsoft Office PowerPoint 2003、Microsoft PowerPoint 2002、Microsoft PowerPoint 2000 和 Microsoft PowerPoint 97 使用。它从当前用户流开始,然后是 PowerPoint 文档流、图片流以及摘要信息、自定义 XML 数据和数字签名的一些可选流。大多数实际内容驻留在 PowerPoint 文档流内的幻灯片容器中。当前用户流包含当前用户 Atom,后者存储用户、版本和系统数据。图片流包含嵌入图像,这些图像引用自它们所在的幻灯片容器。此格式的最小数据单位是“记录”。
用户编辑过程会按顺序存储文件数据。这意味着如果您只想重新创建文件的当前版本,则可以只提取用户最后一次编辑的内容,而无需提取之前的任何数据。同样,通过访问流中用户以前编辑的内容,可以获取文件的以前版本。
注释: |
---|
在 Microsoft PowerPoint 中执行大多数编程任务的推荐方法是使用 PowerPoint 主互操作程序集 (该链接可能指向英文页面)。这些程序集是一组提供可用于 Microsoft PowerPoint 的完整对象模型的 .NET 类。本系列文章只涉及高级方案,如未安装 Microsoft PowerPoint 的情形。 |
MS-PPT 文件格式的重要组件
下面是与 .ppt 文件相关的主要结构。除非另行指定,否则所有结构都驻留在 PowerPoint 文档流中。
- CurrentUserAtom
atom record,指定用户上次修改文件的相关信息,以及最近的user edit所在的位置。它是 CurrentUser stream中的唯一记录。
- UserEditAtom 记录
UserEditAtom 记录包含指向当前编辑的 PersistDirectoryAtom 记录和指向以前的 UserEditAtom 记录的指针及其他一些内容。
- PersistDirectoryAtom 记录
PersistDirectoryAtom 记录指定持久对象目录,后者是一个表,其中包含持久对象标识符以及流相对于可在其中查找持久对象的位置的偏移。每个用户编辑操作都存储持久对象目录,以确定可在其中查找任何新的和修改的持久对象的位置。
- PersistDirectoryEntry 结构
PersistDirectoryEntry 结构是 PersistDirectoryAtom 记录的一部分,并且会逐渐增加。例如persistDirEntry[0], persistDirEntry[1]
。它指定顺序持久对象标识符的压缩表,以及流相对于关联持久对象的偏移。
前 20 位指定持久对象的 ID。接下来的 12 位指定持久偏移条目在 currentPersistDirectoryEntry 结构中的编号。PersistDirectoryEntry 结构的其余部分由偏移条目组成,每个偏移条目使用 4 个字节。如果有多个 PersistOffsetEntry 结构,则每个连续条目都应用其 ID 比前一个条目的 ID 大一的持久对象。
- DocumentContainer 结构
它是一个指定文档相关信息的容器记录,其中包括幻灯片、备注、声音、图形元素和其他内容的列表。当前编辑的所有大纲文本都存储在 DocumentContainer 结构的幻灯片列表中。形状内的文本存储在 Shapes 记录中。
- MainMasterContainer 结构
它是一个指定主母版幻灯片的容器记录。主母版幻灯片定义演示文稿幻灯片的格式和某些内容(如模板图形)。
- SlideContainer 结构
它是演示文稿中幻灯片的容器记录,其中包括切换设置、页眉和页脚信息以及图形元素的指针和格式,还包括一个指定幻灯片版式中使用的占位符形状的 SlideAtom 结构。
- SlideListWithTextContainer 结构
SlideWithTextContainer 结构指定一组 SlideListWithTextSubContainerOrAtom 记录,其中每个记录都包含对演示文稿幻灯片及其所含文本的记录的引用。
- TextCharsAtom 结构和 TextBytesAtom 结构
它们是两种包含文本字符的 SlideListWithTextSubContainerOrAtom 记录。每个结构都包含一个 8 字节记录标头,后跟一系列 Unicode 字符或部分 Unicode 字符。
- DrawingGroupContainer 结构
它是 DocumentContainer 结构的一部分,用于指定图像、艺术字和其他图形内容。
- RecordHeader 结构
RecordHeader 结构是一个 8 字节结构,位于文件中每个容器记录和 Atom 记录的开头。它包含四个字段:recVer、recInstance、recType 和 recLength。后两个字段最值得注意。recType 字段指定当前记录的类型,recLen 字段指定长度(以字节为单位)。
从 PowerPoint 文件提取内容
从采用 MS-PPT 文件格式的 PowerPoint 文档提取内容取决于您要提取的内容种类和具体情况。您可以使用一两个代码页不加选择地获取 .ppt 文件中的所有文本,但这样做将不会保留格式、图形、切换设置,甚至不会保留幻灯片边界。例如,您可以使用类似方法提取所有剪贴画,不过这不在本文的讨论范围之内。若要逐个幻灯片地获取内容,则必须通过读取 PersistDirectoryEntry 记录来标识当前所做编辑。
从 PowerPoint 文件中检索文本
从 PowerPoint 演示文稿中检索纯文本
-
打开 PowerPoint 文档流。
-
对于每个记录:
-
读取记录标头。
-
如果 recType 字段是 TextCharsAtom (0x0FA0) 或 TextBytesAtom (0x0FA8),则将记录的其余部分读取为文本。
-
从 PowerPoint 文件检索幻灯片
理论上,您可以采用与检索纯文本相同的方式重新构造幻灯片平台。例如,通过检查 recType = DocumentContainer/SlideContainer/NotesContainer/ 的记录标头,但这会返回每个编辑阶段的活动幻灯片和过期幻灯片的任意集合,并且没有办法来区分这些幻灯片。但是,如果先构建一个 persist 对象目录,则可以获得所有当前内容的指针,而不获取任何过期内容。
从 PowerPoint 文件检索幻灯片及其内容
-
创建一个 persist 对象目录。
-
创建一个数据结构(如词典),以存储两列链接数据。第一列存储持久对象 ID,第二列存储这些对象在流中的位置的偏移。
-
从 CurrentUser 流读取 CurrentUserAtom 结构。CurrentUserAtom 结构的第 16–19 个字节指定 offsetToCurrentEdit 字段。
-
打开 PowerPoint 文档流,从 CurrentUserAtom.offsetToCurrentEdit 字段指定的偏移读取 UserEditAtom 结构。第 16–19 个字节指定 offsetLastEdit 字段,第 20–23 个字节指定 offsetPersistDirectory 字段。
-
从 UserEditAtom.offsetPersistDirectory 字段提供的偏移读取 PersistDirectoryAtom 结构。
-
使用每个 PersistDirectoryEntry 结构的 ID 值和偏移填充所创建的数据结构。如果 PersistDirectoryEntry 结构具有多个偏移,则为每个连续偏移分别指定一个 ID 值,该值比表中的前一个 ID 大一。
-
转到 UserEditAtom.offsetLastEdit 字段指定的 PowerPoint 文档流中的偏移,读取从此处开始的 UserEditAtom 结构。
-
重复上面三个步骤,直到完成用户编辑。忽略其 ID 值与表中现有 ID 值冲突的任何持久目录条目,因为这些条目表示已被覆盖的幻灯片。
-
-
浏览持久对象目录,检查每个指定偏移处的记录标头,并读取 type = RT_Document 的每个记录。这是 DocumentContainer 结构。
-
在 DocumentContainer 结构中,查找幻灯片列表,该列表是 rh.recType = RT_SlideListWithText 的记录。这是一个 SlideListWithTextContainer 记录,其中包含 SlideListWithTextSubContainerOrAtom 条目的数组。
-
读取该幻灯片列表。每个 SlidePersistAtom 结构 (type = rh.RT_SlidePersistAtom) 的后面都是包含该幻灯片内容的记录。rh.recType = RT_TextCharsAtom 或 rh.recType = RT_TextBytesAtom 的任何记录均包含文本。
-
为幻灯片列表中的每个 SlidePersistItem 结构创建一个包含相应文本内容的幻灯片。
可以对其他幻灯片内容(例如备注、页眉和页脚以及格式信息)使用相同方法。
撤消 MS-PPT 二进制文件格式的历史记录
由于 MS-PPT 二进制文件格式的有序特征,您可以轻松还原 PowerPoint 文件的以前版本。
检索以前版本的 PowerPoint 文件
-
将 PowerPoint 文件的副本加载到内存。
-
在内存中副本中,从 CurrentUser 流读取 CurrentUserAtom 记录。
-
在 PowerPoint 文档流中,从 CurrentUserAtom.offsetToCurrentEdit 字段指定的偏移读取 UserEditAtom 结构。
-
从 UserEditAtom.offsetLastEdit 字段提供的偏移读取前面的 UserEditAtom 结构。
-
删除前面 UserEditAtom 结构之后的所有内容。
-
更新 CurrentUserAtom.offsetToCurrentEdit 字段的值。
-
使用已修改的文件名保存该文件。若要转至以前的已知版本,可以继续往回倒,直至到达正确的 UserEditAtom 结构。
结论
这只是 MS-PPT 格式的示例。借助本文提供的工具,您可以进行简单的数据恢复。经过进一步研究后,您可以开始恢复媒体、格式信息和其他元数据,并最终能够保存操作。