了解 Word MS-DOC 二进制文件格式

**摘要:**了解以前版本的 Microsoft Word 产品中使用的 MS-DOC 二进制文件格式,包括基本结构和重要概念,以便以编程方式与之交互。

上次修改时间: 2012年1月6日

适用范围: Office 2007 | Office 2010 | Open XML | Visual Studio Tools for Microsoft Office | Word | Word 2007 | Word 2010

本文内容
MS-DOC 文件格式概述
结论
其他资源

**发布时间:**2011 年 2 月

**供稿人:**Microsoft Corporation

目录

  • MS-DOC 文件格式概述

  • MS-DOC 文件格式的重要组件

  • 从 Word 文件提取文本

  • 结论

  • 其他资源

本文介绍 MS-DOC 文件的结构和处理 MS-DOC 文件的一些过程。它是介绍 Microsoft Office 产品使用的二进制文件格式的系列文章的一部分。应将这些文章与 MSDN 上提供的 Office File Format Documents结合起来阅读。

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 结构。

  • Character

    字符可以是文本字符或非文本字符(如段落标记或对象锚点)。其大小可能因它是 ANSII、Unicode 还是控制字符而异。文档中的相邻字符在二进制文件中不一定相邻。

    • Character Position (CP)

      字符位置 (CP) 是一个无符号的 32 位整数,它给出字符在文档文本中的索引位置。

    • Pcd 结构

      Pcd 结构指定文本在 Word 文档流中的位置,同时指定文本的一些属性。

  • Plc

    PLC 结构是一个 CP 数组,后跟一个数据元素数组。不同的 Plc 结构具有不同的名称和功能,例如 Plcbkf 结构,它由书签和指向书签的指针组成。

  • PlcPcd 结构

    PlcPcd 结构是一个 PLC 结构,它将一个 CP 数组映射到 Pcd 结构。换言之,它将流中的字符位置映射到文档文本中的字符。

从 Word 文件提取文本

用于检索文本的正式算法在 MSDN 上开放规范文档中的 2.4.1 Retrieving Text下发布,并且在"示例"部分的 3.1 Example of a Clx下给出了一个介绍部分过程的示例。以下是该过程的简化版本。

从 Word 文档提取文本

  1. 将 .doc 文件读入数据流。

  2. 开始在 Word 文档流的偏移 0 处读取文件信息块 (FIB)。有关详细信息,请参阅 2.5.15 How to read the FIB

  3. 在文件信息块内,找到 FibRgFcLcb97 结构。此结构从 FIB 的第 154 个字节开始。它由一系列的 4 字节字段组成。

  4. 在第 268 个字节处读取 FibRgFcLcb97.fcClx 字段,在第 272 个字节处读取 FibRgFcLcb97.lcbClx 字段。这些字段指定 Clx 的偏移位置和大小。

  5. 在 FibRgFcLcb97.fcClx 字段指定的偏移处开始从表格流中读取 Clx 结构。

  6. 在 Clx 结构内,找到 Pcdt,其后紧跟可变长度的 Prc 结构的 .RgPrc 数组

    对于数组中的每个成员:

    1. 读取 .clxt 属性,该属性是 Prc 结构的 0 字节。如果 .clxt = 0x02,表明您已找到 Pcdt。

    2. 如果 .clxt = 0x01,读取后面 2 个字节作为有符号整数,然后跳过该数量的字节来到数组的下一成员。

  7. 在 Pcdt 结构内,找到 PlcPcd 结构,该结构从 Pcdt 的第 5 个字节开始。

  8. 加载 PlcPcd.aPcd 数组和 PlcPcd.aCp 数组。这些数组的成员通过索引值彼此对应。

  9. 对于 PlcPcd.aPcd 中的每个 Pcd 结构:

    1. 在当前 Pcd 结构的第 46 位处读取 Pcd.Fc.fCompressed 字段的值。如果为 0,则 Pcd 结构指代一个 16 位的 Unicode 字符。如果为 1,则指代一个 8 位的 ANSI 字符。

    2. 读取 Pcd.Fc 的值(当前 Pcd 的第 2-5 个字节)以及相应的 CP 值。

      • 如果是 Unicode,则位于当前 CP 值所指定的字符位置处的文本的起始偏移量等于在 Word 文档流中的 Pcd.Fc 值,且每个字符占两个字节。

      • 如果是 ANSI,则位于当前 CP 处的文本开始于 Pcd.Fc 值的一半的偏移量处,且每个字符占一个字节。

      在任一种情况下,当前 CP 指定的字符数都等于数组中下一个 CP 的值减去当前 CP 的值。

结论

本文只是 MS-DOC 格式的一个样本。借助本文提供的工具,您可以进行简单的数据恢复。经过进一步研究后,您可以开始恢复格式信息和其他元数据,并最终执行"保存"操作。

其他资源

有关详细信息,请参阅以下资源: