MS-DOC 文件格式概述
Microsoft Office Word 2003、Microsoft Word 2002、Microsoft Word 2000 和 Microsoft Word 97 都使用 MS DOC 二进制文件格式作为其默认文件格式。这种文件格式适用于任何具有 .doc 或 .dot 扩展名的文件。 Word 文档中的基本数据单位是字符,它可能包括格式字符和其他不可见字符,以及 ANSI 和 Unicode 字符。所有字符数据都驻留在 Word 文档流 中。该流的开头是一个称为文件信息块 (FIB) 的结构,其中包含指向文件中所有数据的指针。
![]() |
---|
在 Microsoft Word 中执行大多数编程任务的推荐方法是使用 Word 主互操作程序集 (该链接可能指向英文页面)。这些程序集是一组提供可用于 Microsoft Word 的完整对象模型的 .NET 类。本系列文章只涉及高级场景,如未安装 Microsoft Word 的场景。 |
MS-DOC 文件格式的重要组件
以下是在处理 .doc 文件时必须了解的一些最重要的结构。
- 2.1.1 WordDocument Stream
Word 文档流是 .doc 文件中的主要流,其中包含文件中的所有数据(表格除外,表格存储在 1Table stream or 0Table stream中)。
- File Information Block
文件信息块从 Word 文档流的偏移 0x00 开始。它指定文件中所有其他数据的位置。位置由一对整数指定,第一个整数指定位置,第二个整数指定大小。这些整数出现在文件信息块的子结构中,如 FibRgFcLcb97。位置名称带有前缀 fc。大小名称带有前缀 lcb。
- Clx 结构
Clx 结构是由零个或多个 Prc 结构组成的包含属性信息的数组,后跟一个 Pcdt 结构,该结构又包含一个 PlcPcd 结构。
- File Information Block
- Character
字符可以是文本字符或非文本字符(如段落标记或对象锚点)。其大小可能因它是 ANSII、Unicode 还是控制字符而异。文档中的相邻字符在二进制文件中不一定相邻。
- Character Position (CP)
字符位置 (CP) 是一个无符号的 32 位整数,它给出字符在文档文本中的索引位置。
- Pcd 结构
Pcd 结构指定文本在 Word 文档流中的位置,同时指定文本的一些属性。
- Character Position (CP)
- Plc
PLC 结构是一个 CP 数组,后跟一个数据元素数组。不同的 Plc 结构具有不同的名称和功能,例如 Plcbkf 结构,它由书签和指向书签的指针组成。
- PlcPcd 结构
PlcPcd 结构是一个 PLC 结构,它将一个 CP 数组映射到 Pcd 结构。换言之,它将流中的字符位置映射到文档文本中的字符。
从 Word 文件提取文本
用于检索文本的正式算法在 MSDN 上开放规范文档中的 2.4.1 Retrieving Text下发布,并且在“示例”部分的 3.1 Example of a Clx下给出了一个介绍部分过程的示例。以下是该过程的简化版本。
从 Word 文档提取文本
-
将 .doc 文件读入数据流。
-
开始在 Word 文档流的偏移 0 处读取文件信息块 (FIB)。有关详细信息,请参阅 2.5.15 How to read the FIB
-
在文件信息块内,找到 FibRgFcLcb97 结构。此结构从 FIB 的第 154 个字节开始。它由一系列的 4 字节字段组成。
-
在第 268 个字节处读取 FibRgFcLcb97.fcClx 字段,在第 272 个字节处读取 FibRgFcLcb97.lcbClx 字段。这些字段指定 Clx 的偏移位置和大小。
-
在 FibRgFcLcb97.fcClx 字段指定的偏移处开始从表格流中读取 Clx 结构。
-
在 Clx 结构内,找到 Pcdt,其后紧跟可变长度的 Prc 结构的 .RgPrc 数组
对于数组中的每个成员:
-
读取 .clxt 属性,该属性是 Prc 结构的 0 字节。如果 .clxt = 0x02,表明您已找到 Pcdt。
-
如果 .clxt = 0x01,读取后面 2 个字节作为有符号整数,然后跳过该数量的字节来到数组的下一成员。
-
-
在 Pcdt 结构内,找到 PlcPcd 结构,该结构从 Pcdt 的第 5 个字节开始。
-
加载 PlcPcd.aPcd 数组和 PlcPcd.aCp 数组。这些数组的成员通过索引值彼此对应。
-
对于 PlcPcd.aPcd 中的每个 Pcd 结构:
-
在当前 Pcd 结构的第 46 位处读取 Pcd.Fc.fCompressed 字段的值。如果为 0,则 Pcd 结构指代一个 16 位的 Unicode 字符。如果为 1,则指代一个 8 位的 ANSI 字符。
-
读取 Pcd.Fc 的值(当前 Pcd 的第 2-5 个字节)以及相应的 CP 值。
- 如果是 Unicode,则位于当前 CP 值所指定的字符位置处的文本的起始偏移量等于在 Word 文档流中的 Pcd.Fc 值,且每个字符占两个字节。
- 如果是 ANSI,则位于当前 CP 处的文本开始于 Pcd.Fc 值的一半的偏移量处,且每个字符占一个字节。
在任一种情况下,当前 CP 指定的字符数都等于数组中下一个 CP 的值减去当前 CP 的值。
- 如果是 Unicode,则位于当前 CP 值所指定的字符位置处的文本的起始偏移量等于在 Word 文档流中的 Pcd.Fc 值,且每个字符占两个字节。
-
结论
本文只是 MS-DOC 格式的一个样本。借助本文提供的工具,您可以进行简单的数据恢复。经过进一步研究后,您可以开始恢复格式信息和其他元数据,并最终执行“保存”操作。