复合文档结构_第1页
复合文档结构_第2页
复合文档结构_第3页
复合文档结构_第4页
复合文档结构_第5页
已阅读5页,还剩8页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、前言网络上,有一篇流传颇广的叫做Excel文件格式的资料,是英文的,老实说,这篇资料对我关于“Excel文件格式”的理解,起到启蒙的作用,但是,进一步老实说,这篇资料对于我的最终工作结果,几乎起不到任何作用。这篇被广泛如获至宝收藏的资料,是基于BIFF2的,BIFF的意思是Binary Interchange File Format(二进制交换文件格式),BIFF2版本的Excel文件并不支持“合并单元格”,这对于我的工作是个致命的打击,无法“合并单元格”,谈何“所见即所得”?所以,我怀疑那些收藏的人,有没有认真的用过这篇资料!当然包括我,我最早得到这篇资料至今少说也有5年了,也是到了最近实在

2、不得不用的时候,才发现了这个问题。这也许是人之常情,被我怀疑的同学们不必为了这个跟我急!既然这样,那就得继续找资料了于是找到一篇excelfileformat,也是英文的,这一篇很好,从BIFF2-BIFF8,非常详尽的阐述了Excel的文件格式,老外们在这方面的态度还是比较认真的,值得学习。但是问题又来了,仅BIFF8版本的Excel文件支持“合并单元格”!这个问题似乎很好解决,按照BIFF8的格式来做不就行了?当然行,是的,可以按照BIFF8的格式来做。做出来的文件也可以被Excel读取,但必须通过两次崩溃、修复后才能使用。为什么?!微软有一个“复合文档格式”,Office从97到2003

3、都采用“复合文档格式”来组织文档,Word、Excel、PowerPoint等等,都采用这种格式来保存。据说微软最新又推出另一种格式,但是问题不大,于我的工作,“复合文档”已经够用了。“裸”的BIFF8版本的Excel文件,用Excel来打开,可能导致读写错误,进而导致崩溃,同时Excel的修复功能能够把它修复成“复合文档”。这是我的理解。有这样的问题,显然是不能提交给客户的。那么就必须给Excel文件“穿上”“复合文档”的外衣,要搞定Excel文件,必须先搞定复合文档。因此,“复合文档”成了通向我的工作的第一只拦路虎(为什么说“第一只”?因为后面还有)!必须解决掉。还得找资料于是又找到一篇c

4、ompdocfileformat,与前面提到的excelfileformat一同出自一个叫做“OpenOffice”的组织。我想我应该谢谢他们。值得一提的是,网上有人说这些文档的结构,微软官方并不公开,是一些黑客通过跟踪、分析等等整理出来,不知是真是假。反正很佩服这些人的毅力。由于我的英文实在太差,有了这些英文的文档,学习起来还是很吃力,就想,会不会有中文资料?找来找去,找到一份叫做复合文档格式研究的资料,作者声称是为了另一篇正在创作的Excel文件格式研究准备的。我为什么没有先搜到这份并不奇怪,因为我在找“Excel文件格式”并不知道“复合文档”作者声称这份中文资料为其“创作”,但扫一眼就看

5、出来这是compdocfileformat的翻译,而且翻译的水平跟“金山词霸”有得一拼,被人追问“记得保存过类似的资料,所以想问一下,这是你原创还是翻译?”之下,于是退缩为“说原创是不可能的,我既不是微软的工程师,也不是世界顶尖黑客。关于excel内部结构,微软是不会公开的,有关的资料也是国外一些黑客用反编译的方法推测出来的。本文是在翻译的基础上,加了一些其他的内容,但都是自己写的。”这世道这篇复合文档格式研究倒是对我的工作起到了很大的帮助作用,我还是得谢谢作者,虽然作者对原文做了大量的删节而不是“加了一些其他的内容”,连章节引用都没改,可见确实“都是自己写的”。资料齐了,可以动手了。不知道是

6、因为东西方的文化差异造成的,还是我的基础实在太差,很多地方很难懂,做的过程相当痛苦。从开始找资料到第一个Excel文件的输出,整整花了三周的时间,折腾之下,也就有了一点心得,于是决定记录下来,那得有个地方记,于是决定重开博客。对于复合文档,由于并非小狮原创,也谈不上“研究”,于是叫做复合文档学习笔记。一向,我主张不管学术本身如何晦涩,写出来,也要尽量让毫无基础的人能够看懂。而且我也是个很啰嗦的人,写成文字可能就相当“冗余”。但我自己又是一个很善于遗忘的人,既然是笔记,那也要预着将来自己把相关知识忘个一干二净以后再来看能看得懂,有利于自己再学习,于是就要一如既往的“啰嗦”了。本文基本上按照我自己

7、的学习经过来写,重点在我认为难懂的地方阐述自己的见解。当然,你也可以认为我是在“翻译一些资料”,但我实在不敢用“翻译”二字,问题就因为“我的英文实在太差”,英文原文可能已经很详尽了,我的这一篇也可能是“添足之笔”,但我保证这是我“自己写的”。原文compdocfileformat和excelfileformat都是老外牛人的心血,不敢窃为己有,提供链接:复合文档格式/compdocfileformat.pdf、Excel文件格式/excelfileformat.pdf。如果你只是想了解这些结构,而且基础

8、及英文还行,看原文就可以了。如果你想要看中文的,而且受得了我的啰嗦,那就看我的。当然还要有耐心,这是第一篇,我很忙,第二篇什么时候写就不一定了。但我想我会在忘了这些之前把它写完。头部原创:弄潮小狮从前文谈及的两份来之OpenOffice的文档看,compdocfileformat(复合文档文件格式)只有区区200来KB,excelfileformat(Excel文件格式)却超过1MB,看起来,Excel文件的结构似乎比复合文档复杂5倍?实际上,Excel文件格式相当简单,复合文档的文件格式却要复杂的多。本文很多说法来源或翻译于compdocfileformat一文,若无特别说明,本文所指“英文

9、原文”即指该文。下文提及的“复合文档”均指“微软复合文档”。摆弄文件格式,于小狮来讲,历史已经不短了,如果也可以说是资历的,那可谓“老”了。最早应该在15年前,为了在Dos下用TC显示一幅BMP图片,连猜带蒙,搞定了BMP的文件格式,如果那时候知道这样做就能够成为黑客的话,那遐想中接下来就是几年前学习了一下PE,后来又搞了反汇编,顺带把com文件的格式也摸索了,熟悉我的朋友应该知道,做这些事为了一个“PB神盾”,也只是应用在自己的一些产品上,有朋友跟我说这个东东商机大大的又遐想摆弄文件结构,需要一些知识准备:字节、字、整数、浮点数、结构体等等,还有数制转换、ANIS、Unicode等等我相信很

10、多人对这些知识已经滚瓜烂熟了,嗤之以鼻、不屑一谈。曾经有牛人由于太精通PB,以至于把硬盘文件分为“二进制文件”(或者流文件)及“文本文件”,有鉴于此,为了准备让基础薄弱如小狮者能够理解本文,是有必要就有关知识啰嗦啰嗦的。但本文又不是要讲这些,只能有机会另外撰文了,本文就先假设读者已经对上述知识滚瓜烂熟了鉴于有人称微软未公开复合文档等的文件结构,手头资料又并非微软官方文档,那么就意味官方术语可能并不存在,本文中有关术语、定义或者说法,或小狮自己的理解,或人云亦云、以讹传讹,或来源于对有关文档的翻译,小狮的翻译水平又确实有限,难免谬误,深表歉意之余,欢迎指正。但谢绝引为学术依据,否则后果自负,这算

11、是免责声明。为了形象的表示复合文档的结构,以便下一步工作的校验,小狮专门为此用Delphi编写了一个名叫复合文档查看器的小程序,若无特别说明,本文插图均为该程序的运行结果。复合文档的头部存放于文件开头的512(200h)个字节,这是固定的,头部存放的信息,基本上反映了整个文件的总体概貌。小狮注:作为头部,大多数文件都用固定的字节数存放在文件的开头。但这并非固定的标准,有些头部是可变长度的,有些文件的头部则存放于文件的末尾,可见,“头部”仅仅是个称谓,并不等于“开头部分”,这不是翻译的问题,英文原文写做“Header”,大约是有来由的。如果“Header”确实又有“尾部”的意思,那就是小狮翻译水

12、平的问题了。但复合文档的“头部”确实位于文件开头的的512个字节,这就使得中华儿女们对此的理解不会有歧义,这很好!还有一句废话得讲讲,本文中涉及数字后面带个“h”的,说明是个十六进制数,如前文的200h,换算为十进制就是512。有些地方直接用十六进制而没有相应的换算为十进制,其一是小狮偷懒了,其二有些数值用十进制表示,于业内人士而言,反而不好表达。当然,如果读者认为我不懂换算,那我也管不了废话讲多了,该入正题了,先看图1:图1图1是一个示例文件的头部,为了更能说明问题,我选择了一个16.4 MB那么大的文件来作为示例,为什么这么做?后面会讲到。再啰嗦一下,在计算机科学中,计数一般从0开始,本文

13、也这么做,其一是为了更像那么回事,其二在Delphi编程方便。如图1所示:头部从0字节开始的8个字节,是复合文档的标识,8个字节的值依次是D0h、CFh、11h、E0h、A1h、B1h、1Ah、E1h。如果这8个字节不是这些值,那么这个文件就不是复合文件,当然,刚好是这些值,那也不能说就是8至23一共16个字节,英文原文称“Unique identifier (UID) of this file (not of interest in the following, may be all 0)”,大意是“文件唯一标识,可能全部是0”,老实说,我没搞明白这个标识有什么用,手头用来做实验的文件也没找

14、到一个不是全0的,自己生成的文件里面添上全0也没发生过什么事故,因此个人认为,这个当它全0就行了,不用管它,因此复合文档查看器也没有把它显示出来。24(18h)至25两个字节,是一个16位整数,固定值为003Eh,文件格式的修订号。26(1Ah)至27两个字节,是一个16位整数,固定值为0003h,文件格式的版本号。28(1Ch)至29两个字节,是一个16位整数,值为FFFEh或FEFFh,字节排序方式。解释这个必须依赖WinHex,图2是WinHex打开示例文件的截图:图2(WinHex截图)图中:28(1Ch)字节的值是FEh,29(1Dh)字节的值是FFh,合起来,作为一个16位(2个字

15、节)整数,它的值是FFFEh,这就是说,低字节在前,高字节在后。其实,这个在英文原文中有举例说明(第9页,4.2 Byte Order),其中说明很详细,我就不照译了,但这对于初涉其中的同学很容易混淆,所以专门说一下。另外就是,按照原文的说法,FFFEh表示“Little-Endian”(这个词我不知道怎么翻译,意即低字节在前),FEFFh表示“Big-Endian”(这个词我不知道怎么翻译,意即高字节在前),那么,对于本字段而言,不管采用何种方法进行储存,其储存结果都如图2所示,这就很麻烦(其实小狮也完全搞不懂),所幸,英文原文又称“在现实应用中,只采用前者”,这就没什么问题了,我们直接把这

16、个值固定为FFFEh,而且“Little-Endian”符合内存读写规律,省去很多转换。幸甚!幸甚!30(1Eh)至31两个字节,是一个16位整数,值通常为9,表示一个扇区的大小,是2的幂,值为9表示29,即512个字节,这个值不是固定的,但通常是9。扇区:英文“sector”,我不知道原文是否有“扇形区域”的意思,但“扇区”的叫法本身有点意思,这个有机会再写,在本文中,只需要把它理解为一个“存储块”就行了。32(20h)至33两个字节,是一个16位整数,值通常为6,表示一个短扇区的大小,是2的幂,值为6表示26,即64个字节,这个值不是固定的,但通常是6。短扇区:英文“short-secto

17、r”,这个概念我也是第一次接触,英文原文有解释(第12页,6.1 Short-Stream Container Stream),就不翻译了,我的理解是它“集装”(原文用了“Container”这个词)于扇区中。由此,对这两个字段用2的幂来表示就很好理解,也只有这样,只要后者不大于前者,一个扇区就刚好能够“装下”整数个短扇区。接下来从34(22h)至43共10个字节,英文原文称“Not used”,也就是不使用,这与其他文档的表述有点区别(别的文档称“保留”),我不知道是否是一样的意思,也不知道这10个字节是否真的不被使用,实际上这10个字节的值总是0。复合文档查看器也没有把它显示出来。44(2

18、Ch)至47四个字节,是一个32位整数,表示分区表扇区的总数,这个值跟文件大小有关。分区表:英文原文“sector allocation table”(缩写SAT),意为“扇区分配表”,我把它称为“分区表”,其一是我记得磁盘系统有这种叫法,其二是为了下本提及时少打几个字。在复合文档中:除了头部,其余存储空间按扇区大小划分成若干个扇区(你可以发现一个复合文档的字节总数总是512的整数倍),用分区表进行管理,而分区表本身也存储于扇区,这个字段表示用来存储分区表的扇区的总数。事实上,这种空间分配机制跟微软赖以起家的磁盘系统的分配机制极其类似。大家都知道格式化磁盘的时候有一种“快速格式化”,其实就是重

19、建一个磁盘分区表,仅此而已。48(30h)至51四个字节,是一个32位整数,表示目录流第一个扇区的ID,ID这个词,用途太广泛了,在这里是编号的意思,小狮习惯称之为“编码”。扇区编码:前面讲过,在复合文档中,除了头部,其余存储空间按扇区大小划分成若干个扇区,紧跟着头部的那个扇区就是第一个扇区,编号为0(从0开始编码),这样,从扇区编码就可以很容易的计算出扇区相对于文件开始位置的偏移量,示例中:目录流第一个扇区的ID为1,则偏移量=头部大小(512)+扇区编码(1)×扇区大小(512)=1024(400h)。接下来52(34h)至55四个字节又是“Not used”,不使用。复合文档查

20、看器也没有把它显示出来。56(38h)至59四个字节,是一个32位整数,表示最小标准流尺寸,值通常为4096(1000h),当一个流的大小不小于这个值时,采用扇区(标准流)储存,否则采用短扇区(短流)储存,我不知道这种机制的好处在哪里,但人家这样做,我想自有道理吧?在文件处理的时候,时空开销上应该能够得到优化,但我不确定。流:先贤们从西方文献中直译过来的,原文“stream”我不知道是否有其他译法,但“流”已经成为计算机科学中的一个基本术语,意思大约是“连续的数据信息”,其实我很难表述这个概念,也解释不好。便于理解起见,你可以将它当作文件系统中的一个文件来看待。60(3Ch)至63四个字节,是

21、一个32位整数,表示短分区表(缩写SSAT)的第一个扇区的ID,类似分区表,短分区表是用来管理短扇区的。值为FFFFFFFFh(-1)时,表示短分区表不存在。如前所述,如果复合文档的所有“流”的大小均不小于“最小标准流尺寸”,则没有采用短扇区来储存的“流”,当然短扇区就不存在,也不需要所谓的短扇区分区表来管理。64(40h)至67四个字节,是一个32位整数,表示短分区表扇区总数,类似分区表,短分区表也需要扇区来储存。68(44h)至71四个字节,是一个32位整数,表示主分区表(缩写MSAT)的第一个扇区的ID。前面讲到“分区表(SAT)”、“短分区表(SSAT)”,现在又冒出了一个“主分区表(

22、MSAT)”,后面会有一篇专门来认识它们。要理解这个字段,还得借助接下来的两个字段,先接着说72(48h)至75四个字节,是一个32位整数,表示主分区表的扇区总数。从76(4C)开始到头部结束,一共436个字节,为109个32位整数(可以看作数组),为主分区表的开头109个记录,每个记录为分区表扇区的编码(即ID)。当分区表扇区的个数(44(2Ch)至47)大于109个时,就需要另外的扇区来存储,前一个字段“主分区表的扇区总数”表示的就是“另外的扇区”的个数,而再前一个字段“主分区表的第一个扇区的ID”就表示这“第一个另外的扇区”的编码。当分区表扇区的个数不大于109个时,整个主分区表就存储于

23、头部,不再需要“另外的扇区”。那么,“主分区表的第一个扇区的ID”的值为FFFFFFFFh(-1),“主分区表的扇区总数”的值为0。当需要两个以上的“另外的扇区”来储存主分区表时,接下来的扇区如何寻址,下一篇再讲拗口!早就说了,小狮是个极为啰嗦的人,一个头部就写了这么多,后面还有不少内容,不知什么时候才是个头。先整理一些概念:扇区:在复合文档中:除了头部,其余存储空间被划分成大小相等的存储区域,这些区域就叫做“扇区”。短扇区:短扇区应该是复合文档中特有的一个概念(恕我孤陋寡闻,在其他格式文件中,未见过这个概念),根据有关资料介绍及小狮本人的实践,在复合文件中,特定的一些扇区又被划分成大小相等的

24、更小(相对于扇区)存储区域,这些区域就叫做“短扇区”。这个概念有点难理解,我在学习过程中有这样的感觉,希望通过下文的描述,可以更清晰的给读者朋友勾勒出来。扇区编码(ID):在复合文档中,扇区按顺序进行编码,紧跟着头部的那个扇区就是第一个扇区,编号为0(从0开始编码)。 扇区偏移量:扇区第一个字节在复合文档中的绝对位置。短扇区偏移量:短扇区第一个字节在复合文档中的绝对位置。分区表:是一个32位整数的数组,按下标与扇区一一对应,数组的每成员的值表示在流中紧接相对应的扇区的下一个扇区(即该扇区的后续扇区)的编号,这就形成了一个链表,将相关的扇区“串接”起来,形成一个完整的“流”。有几个特殊

25、的值:FFFFFFFFh(-1),表示该扇区为自由扇区(未被使用);FFFFFFFEh(-2),表示链表结束(没有后续扇区);FFFFFFFDh(-3),表示该扇区被分区表使用;FFFFFFFCh(-4),表示该扇区被主分区表使用。英文原文有更详细的描述(第7页,3.2 Sector Chains and SecID Chains)。短分区表:类似分区表,不同的是短分区表用来管理短扇区。通常,数组成员的特殊值只有FFFFFFFFh(-1)和FFFFFFFEh(-2),因为分区表及主分区表不会使用短扇区来储存。分区表扇区:用来储存分区表的扇区,就叫做“分区表扇区”。短分区表扇区:用来储存短分区表

26、的扇区,就叫做“短分区表扇区”。主分区表:主分区表主要是用来管理分区表扇区的,它与前述两种分区表有个重要的区别:前两者是“链表”的形式,主分区表是一个彻头彻尾的数组,它的每一个成员的值直接指向对应的扇区,特殊值只有FFFFFFFFh(-1)。“主分区表”这个词直接翻译于英文原文,或许这个词不够恰当,但我想不出另一个更有利于表述的词来。主分区表扇区:用来储存主分区表的扇区,就叫“主分区表扇区”。流:如前文所述,先贤们从西方文献中直译过来的,原文“stream”我不知道是否有其他译法,但“流”已经成为计算机科学中的一个基本术语,意思大约是“连续的数据信息”,其实我很难表述这个概念,也解释不好。便于

27、理解起见,你可以将它当作文件系统中的一个文件来看待。短流:流尺寸小于特定数值的流,在复合文档中,这个值通常为4096(1000h)。目录流:用来存储目录的流,在复合文档中,这是一个特殊的流,它由复合文档直接管理,而不由目录系统管理。原因应该是它本身描绘了目录的结构,目录记录了流的入口,“由目录管理目录流的入口”,显然是行不通的。这些概念,几乎都有个“区”字,到底哪个本身就是“区”,哪个用来管理“区”的,很容易混淆。其实英文更容易混淆,都有“sector”这个词。如果你现在还是很难理解分区表的概念,你可以将分区表理解成一份标注复合文档存储空间的“地图”。在复合文档中:主分区表始于头部第76(48

28、h)个字节,为一个32位整数的数组,至头部结束,共436个字节,可存放109个分区表扇区编码,当分区表扇区的个数不止109个的时候,就需要额外的扇区进行存放,这些“额外的扇区”就叫做“主分区表扇区”。通常,一个扇区的大小为512个字节,那么,一个主分区表扇区就能够储存128个分区表扇区编码?实际上,每个主分区表扇区只储存127个分区表扇区编码,因为每一个主分区表扇区的最后4个字节(一个32位整数)用来存放下一个主分区表扇区的编码。这样,当分区表很大的时候,才能够将主分区表按顺序“串”起来,主分区表已经是最顶级“地图”了,它只能用这种方式来进行“串接”。事实上,按照复合文档学习笔记(二)-头部中

29、的示例(图1),在这个文件中,分区表扇区的个数有263个,头部储存109个,还有154个扇区编码需要储存,那就需要“额外的扇区”,一个主分区表扇区储存127个扇区编码,154个扇区编码就需要2个扇区来存储,即2个主分区表扇区。有一点我没搞清楚的是,前面讲过“每一个主分区表扇区的最后4个字节(一个32位整数)用来存放下一个主分区表扇区的编码”,那么,如果分配到最后一个扇区剩下128个扇区编码,剩下一个又需要一个扇区来储存,这显然很浪费,这时候,这4个字节是否直接存放的最后一个分区表山区编码?这种情况英文原文没有提及,小狮也没有去做测试,你知道,有找一个(或者专门做一个)这样的文件,是一件痛苦的事

30、情。在主分区表中,每一个成员的值表示一个扇区编码,FFFFFFFFh(-1)表示该扇区是空闲扇区。按照主分区表的顺序,将这些扇区“串起来”,逻辑上就形成一个连续的数据串(扇区偏移量的计算方法见复合文档学习笔记(二)-头部),这个“数据串”就是分区表。分区表也是一个32位整数的数组,但其用法与主分区表是截然不同的,分区表按照数组下标,对应扇区,譬如:分区表的第0个成员,就对应0扇区。每个成员的值表示紧接该扇区(下一个扇区)的扇区编码(扇区偏移量计算方法同“主分区表”),这就形成一个链表,这在英文原文中也有例子说明,这里我也简单据一个例子。譬如:分区表的第0个成员,就对应0扇区,其值为1,就表示,

31、在流中,紧接0扇区的下一茬数据存放在1扇区中。链表在何处结束?当一个分区表成员的值为FFFFFFFEh(-2)时,表示“下面没有了”,链表到此结束。还有两种特殊的扇区:值为FFFFFFFDh(-3)时,表示这个扇区被分区表占用(即分区表扇区);值为FFFFFFFCh(-4)时,表示这个扇区被主分区表占用(即主分区表扇区)。还有一个值:FFFFFFFFh(-1),表示这个扇区是空闲扇区,这通常出现在分区表的末尾。如前例:分区表的最后100个成员,其值都是FFFFFFFFh(-1)。短分区表也是一个32位整数的数组。第一个短分区表扇区编码由头部获得,短扇区分区表由分区表管理,获得第一个短分区表扇区

32、编码后,通过分区表“串接”,就可获得完整的短扇区分区表。其用法与分区表类似,但短扇区偏移量寻址有点麻烦,这个将在下一篇结合“目录和目录流”进行讲述。本篇讲起来已经很绕了,为了方便阅读,小狮将可能引起混淆的有关词汇加蓝,并下划线表示,并非URL,转载时请保留原貌,谢谢!目录及目录流原创:弄潮小狮通过前面的讲述,我们已经知道了复合文档如何对存储空间进行管理,这是远远不够的,我们不仅要知道复合文档中的数据,更要知道这些数据表达什么?又如何管理?这就是本篇要讲述的“目录及目录流”,这也需要先整理几个概念:目录:如果说,分区表是一份复合文档的物理地图的话,那么,目录就是一份“逻辑地图”,它将告诉我们,在

33、符合文档中的流是如何被组织、被使用的,以及流的存储位置、大小等等。目录流:前面讲过,目录流是用来储存目录的流,由复合文档直接管理。目录树:从DOS时代过来的朋友对“目录树”应该不会陌生,没见过DOS的朋友,也有比较直观的学习途径,在Windows下面,有“文件夹”(其实就是DOS的“目录”),文件夹里面又包含文件夹、文件,这就形成了一个树形结构,从“根”到“枝”、“叶”。红黑树:事实上,我不记得上学的时候学过这个概念(或者说“数据结构”),在此之前连听都没听说过,资料显示,“红黑树”早在1978年已经面世,也许是我上学不认真所致,惭愧!因此,在学习复合文档的时候,我又不得不花了不少时间“恶补”

34、一课(这是我碰到的另一只拦路虎)。要详细讲述这个概念以及实现方法等等,可能会需要很长的篇幅,但简单地说,红黑树是二叉树的一种,有兴趣(或者有需要)的朋友可以自己找资料了解,在网上,这方面的资料不少。目录入口:英文原文“Directory Entry”,一个说明目录及其相关信息的结构。既然目录流由复合文档直接管理,那么,如何读取目录流?根据前面几节的描述,在头部可以找到目录流的第一个扇区的编码(ID)(见:复合文档学习笔记(二)图1),根据该编码,从分区表(SAT)中可以读取目录流的扇区链,见图3:图3按照目录流的扇区链的顺序,读取每个扇区的数据,“串起来”就是目录流了。每个目录入口有128(8

35、0h)个字节,一个复合文档至少必须有一个目录(即“根入口”,Root Entry),在默认情况下,它大于短扇区尺寸(26),因此,目录流总是以扇区来存储。实际上,不管短扇区尺寸如何设置,目录流不可能以短扇区来存储,这个问题本文最后会谈到。示例中读出的目录流数据见图4:图4(WinHex截图)从图4可以看到,目录流按每128个字节一个目录入口按顺序存放,以第一个目录入口为例,在128个字节的目录信息中:0(00h)至63(3Fh)共64个字节,存放目录入口名称,采用Unicode字符,是一个0值字符终止的字符串。64(40h)至65(41h)共2个字节,是一个16位整数,表示目录入口名称的长度(

36、包括终止符0)。第66(42h)字节,是一个8位整数,表示目录入口的类型:1(01h)表示目录是一个仓(这个“仓”有点怪,英文原文为“storage”,我想可以理解为相当于一个文件夹);2(02h)表示目录是一个流;5(05h)表示目录是根,在复合文档,通常有且仅有一个这样的目录,并且总是第一个,我不知道有没有例外,在我学习的过程中未确实碰到例外的情况。其他值,英文原文语焉不详,我在学习过程中也没碰到过,这里不做描述,以免以讹传讹。第67(43h)字节,是一个8位整数,表示目录入口节点在红黑树中的颜色:0(00h)表示红色,1(01h)表示黑色。68(44h)至79(4Fh)共12个字节,是三个32位整数,这三个整数的前两个被应用于红黑树中,按顺序分别表示左孩子的目录编码和右孩子的目

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论