复合文档格式研究之04 -Header的读取

李懿 Excel学习 2016-07-05

 

微信扫一扫
关注该公众号

复合文档解析实践—Header的读取

4.1 Header结构分析

在微软的MS-CFB官方文档第16页中,复合文档文件头(Header)占用512个字节,其结构如下:


 19         复合文档文件头结构

 

Header Signature (8 bytes):区别文件类型的文件头,固定为D0, CF,11, E0, A1, B1, 1A, E1.

Header CLSID (16 bytes): 保留字节,全都是0

Minor Version (2 bytes):文件小版本号,固定为3E

Major Version (2 bytes):文件主版本号,有3个4两种值,反正这里都是3

Byte Order (2 bytes):固定为FFFE,表示Little Endian

Sector Shift (2 bytes):表示每个扇区的大小。2和这里的数字做指数运算后即为扇区的大小。只有两种值可选,9和C,即9和12,分别表示512字节和4096字节,也分别对应了版本号3和4。

Mini Sector Shift (2 bytes):固定为0006,表示Mini扇区的大小,也就是64个字节

Reserved (6 bytes):保留字,全都是0

Number of Directory Sectors (4 bytes): Directory Sectors的数量,就是目录扇区的数量。若版本号为3,则该值为0

Number of FAT Sectors (4 bytes): FAT扇区的数量

First Directory Sector Location (4 bytes):文件目录流的起始扇区编号

Transaction Signature Number (4 bytes):都是0,没啥用

Mini Stream Cutoff Size (4 bytes):固定为00001000。表示文件最小的存储大小,为4096,即4k

First Mini FAT Sector Location (4 bytes): mini FAT的起始扇区编号

Number of Mini FAT Sectors (4 bytes): mini FAT的数量

First DIFAT Sector Location (4 bytes): DIFAT的起始扇区编号

Number of DIFAT Sectors (4 bytes): DIFAT的数量

DIFAT (436 bytes):包含了109个DIFAT,每个DIFAT占用4个字节。

4.2 定义Header类型

根据上述的描述,可以定义一个数据类型,来存放文件头的各种信息。根据数据不同的字节长度,声明不同的数据类型,可以完美且方便地获取各种信息。我们用的最多的也就3种类型的数据:Byte表示1个字节,Integer表示2个字节,Long表示4个字节。如果超过的,可以再用数组。然后将所有的Header元素表示成不同的数据类型,最终定义我们的Header类型如下:

Private Type CFBHeader                      ' 复合文件文件头类型

    HeaderSig(0 To 7)       As Byte         ' Header Signature

                                                                  '. 0xd0 0xcf 0x11 0xe0

                                                                  '  0xa1 0xb1 0x1a 0xe1

    CLSID(15)                   As Byte         ' Header CLSID

    MinorVersion              As Integer      ' Minor Version

    MajorVersion              As Integer      ' Major Version

    ByteOrder                   As Integer      ' 0xFFFE  Little Endian

    SectorShift                 As Integer      ' Sector Shift

    MiniSectorShift           As Integer      ' Mini Sector Shift

    Reserved(5)                As Byte         ' 保留字,6字节,都是0

    DirSecCount               As Long         ' Number of Directory Sectors

    FATCount                   As Long         ' FAT 数量

    DirSecStart                 As Long         ' First Sector of the Directory

    TransSig                     As Long         ' Transaction Signature

                                                                  ' Number , 都是0

    MiniSectorCutoff          As Long        ' Mini Stream Cutoff Size

    MiniFatStart                As Long         ' Mini FAT 起始

    MiniFatCount              As Long         ' Mini FAT 数量

    DIFATStart                 As Long         ' DIFAT 起始

    DIFATCount               As Long         ' DIFAT 数量

    DIFAT(108)                As Long         ' 最早的109个FAT

End Type

 

4.3 读取Header

接下去的工作就十分容易了,在第三部分我们介绍的读取方法中,只要按照Header的数据类型读取一次Header就行了,代码如下:

Sub ReadHeader()

    Dim Hdr     As CFBHeader    ' Header

    Dim FS      As Integer            ' File No.

    FS = FreeFile                        ' 获取一个文件流

    '打开文件

    Open ThisWorkbook.Path & "\test.xls" For Binary Access Read As FS

    '读取文件头

    Get FS, , Hdr

    Close FS                                ' 关闭文件流

    Stop

End Sub

运行一下,再打开“本地窗口”,我们看到所有的信息都一目了然,实在太棒了。


 20         读取Header示例

4.4 进制转换

细心聪明的你一定发现了有什么不太对劲的地方,是什么呢?我们看下ByteOrder这个属性,官方文档给出的是FFFE,而你在程序里面看到了什么?-2(十进制数字)!我们都不是计算达人,怎么能快速确定-2就是FFFE呢?这里介绍一个我个人比较倾向的方法:声明一个十六进制的常量来表示官方文档中的各个常量值。

比如ByteOrder,用以下语句声明:

 

Public Const cByteOrder As Long = &HFFFE

 

VBA中表示一个十六进制数字,就得以&H为开头,后面则可以直接写该数。这个十六进制的数字是可以直接和十进制数字进行任何运算和比较的。我们来确认一下这个读取出来的ByteOrder是否就是官方文档中介绍的ByteOrder。我们运行刚才的程序,待运行至Stop语句的时候,打开“立即窗口”,在里面输入以下语句并按回车,你会得到如下结果:


 21         比较常量

4.5 小结

至此,聪明的你其实已经已经学会了解析复合文档所需要的大部分知识了。如果到这里还没看明白的话,建议你多看几次,并用实际程序运行并比较一下官方文档。接下去,我们要介绍一个非常重要的内容,也是很多文档都犯错的地方:如何通过DIFAT和FAT来确定Sector以及其中的数据。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值