您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 信息化管理 > 复合文档的二进制存储格式
复合文档的二进制存储格式研究(word,xls,ppt...)前言复合文档(CompoundDocument)是一种不仅包含文本而且包括图形、电子表格数据、声音、视频图象以及其它信息的文档。可以把复合文档想象成一个所有者,它装着文本、图形以及多媒体信息如声音和图象。目前建立复合文档的趋势是使用面向对象技术,在这里,非标准信息如图像和声音可以作为独立的、自包含式对象包含在文档中。MicrosoftWindows就是使用这种技术,叫做“OLE2storagefileformat”或“MicrosoftOfficecompatiblestoragefileformat”。当然Excel、Word等都是用这种格式存储的。本文主要研究复合文档的二进制结构。目录第一章仓库与流(StoragesandStreams)第二章扇区与扇区链(SectorsandSectorChains)第三章复合文档头(CompoundDocumentHeader)第四章扇区配置(SectorAllocation)第五章短流(Short-Streams)第六章目录(Directory)第七章Excel文件实例剖析第一章仓库与流复合文档的原理就像一个文件系统(文件系统:如FAT与NTFS)。复合文档将数据分成许多流(Streams),这些流又存储在不同的仓库(Storages)里。将复合文档想象成你的D盘,D盘用的是NTFS(NTFileSystem)格式,流就相当于D盘里的文件,仓库就相当于D盘里的文件夹。流和仓库的命名规则与文件系统相似,同一个仓库下的流及仓库不能重名,不同仓库下可以有同名的流。每个复合文档都有一个根仓库(rootstorage)。例:第二章扇区与扇区链2.1扇区与扇区标识所有的流又分成更小的数据块,叫做数据扇区(sectors)。Sectors可能包含控制数据或用户数据。整个文件由一个头(Header)结构以及其后的所有Sectors组成。Sectors的大小在头中确定,且每个Sectors的大小都相同。以下为示意图:HEADERSECTOR0SECTOR1SECTOR2SECTOR3SECTOR4SECTOR5SECTOR6┆Sectors简单的以其在文件中的顺序列举,一个扇区的索引(从0开始)叫做扇区标识(SID:sectoridentifier)。SID是一个有符号的32位的整型值。如果一个SID的值非负,就表示真正存在的那个Sector;如果为负,就表示特殊的含义。下表给出有效的特殊SID:SIDNameMeaning–1FreeSID空闲sector,可存在于文件中,但不是任何流的组成部分。–2EndOfChainSIDSID链的结束标记(见2.2节)–3SATSID此Sector用于存放扇区配置表(SAT)(见4.2节)–4MSATSID此Sector用于存放主扇区配置表(MSAT)(见4.1节)2.2扇区链与扇区标识链用于存储流数据的所有Sectors的列表叫做扇区链(SectorChain)。这些Sectors可以是无序的。因此用于指定一个流的Sectors的顺序的SID数组就称为SIDchain。一个SIDchain总是以EndOfChainSID(-2)为结束标记。例:一个流由4个Sector组成,其SID链为[1,6,3,5,–2]。流的SID链是通过扇区配置表构建的(见4.2节),但短流和以下两种内部流除外:1.主扇区配置表,其从自身构建SID链(每个扇区包含下一个扇区的SID)。2.扇区配置表,其通过主扇区配置表构建SID链。第三章复合文档头3.1复合文档头的内容复合文档头在文件的开始,且其大小必定为512字节。这意味着第一个Sector的开始相对文件的偏移量为512字节。复合文档头的结构如下:OffsetSizeContents08复合文档文件标识:D0HCFH11HE0HA1HB1H1AHE1H816此文件的唯一标识(不重要,可全部为0)242文件格式修订号(一般为003EH)262文件格式版本号(一般为0003H)282字节顺序规则标识(见3.2)::FEHFFH=Little-EndianFFHFEH=Big-Endian302复合文档中sector的大小(ssz),以2的幂形式存储,sector实际大小为s_size=2ssz字节(一般为9即512字节,最小值7即128字节)322short-sector的大小(见5.1),以2的幂形式存储,short-sector实际大小为s_s_size=2sssz字节(一般为6即64字节,最大为sector的大小)3410Notused444用于存放扇区配置表(SAT)的sector总数484用于存放目录流的第一个sector的SID(见6)524Notused564标准流的最小大小(一般为4096bytes),小于此值的流即为短流。604用于存放短扇区配置表(SSAT)的第一个sector的SID(见5.2),或为–2(EndOfChainSID)如不存在。644用于存放短扇区配置表(SSAT)的sector总数684用于存放主扇区配置表(MSAT)的第一个sector的SID(见4.1),或为–2(EndOfChainSID)若无附加的sectors。724用于存放主扇区配置表(MSAT)的sector总数76436存放主扇区配置表(MSAT)的第一部分,包含109个SID。3.2字节顺序(ByteOrder)文件数据的二进制存储有两种方法Little-Endian和Big-Endian,但实际应用中只使用Little-Endian方法即:低位8字节存放在地址的低位,高位8字节存放在地址的高位。例:一个32位的整数13579BDFH(转为十进制即324508639),以Little-Endian存放为DFH9BH57H13H,以Big-Endian存放为13H57H9BHDFH。(H下标表示十六进制)3.3扇区偏移量从头中的信息可以计算出一个sector的偏移量(offset),公式为:sec_pos(SID)=512+SID?s_size=512+SID?2ssz例:ssz=10andSID=5:sec_pos(SID)=512+SID?2ssz=512+5?210=512+5?1024=5632.第四章扇区配置4.1主扇区配置表主扇区配置表(MSAT:mastersectorallocationtable)是一个SID数组,指明了所有用于存放扇区配置表(SAT:sectorallocationtable)的sector的SID。MSAT的大小(SID个数)就等于存放SAT的sector数,在头中指明。MSAT的前109个SID也存放于头中,如果一个MSAT的SID数多余109个,那么多出来的SID将存放于sector中,头中已经指明了用于存放MSAT的第一个sector的SID。在用于存放MSAT的sector中的最后一个SID指向下一个用于存放MSAT的sector,如果没有下一个则为EndOfChainSID(-2)。存放MSAT的sector的内容:(s_size表示sector的大小)OffsetSizeContents0s_size-4MSAT的(s_size-4)/4个SID的数组s_size-44下一个用于存放MSAT的sector的SID,或-2(已为最后一个)最后一个存放MSAT的sector可能未被完全填满,空闲的地方将被填上FreeSID(-1)。例:一个复合文档需要300个sector用于存放SAT,头中指定sector的大小为512字节,这说明一个sector可存放128个SID。MAST有300个SID,前109个放于头中,其余的191个将要占用2个sector来存放。此例假定第一个存放MSAT的sector为sector1,则sector1包含127个SID。第128个SID指向一个用于存放MSAT的sector,假定为sector6,则sector6包含剩下的64个SID(最后一个SID为-2,其他的值为-1)。4.2扇区配置表扇区配置表(SAT:sectorallocationtable)是一个SID数组,包含所有用户流(短流除外)和内部控制流(theshort-streamcontainerstream,见5.1,theshort-sectorallocationtable,见5.2,andthedirectory,见7)的SID链。SAT的大小(SID个数)就等于复合文档中所存在的sector的个数。SAT的建立就是通过按顺序读取MSAT中指定的sector中的内容。存放SAT的sector的内容:(s_size表示sector的大小)OffsetSizeContents0s_sizeSAT的s_size/4个SID的数组当通过SAT为一个流创建SID链时,SAT数组的当前位置(arrayindex)表示的就是当前的sector,而该位置存放的SID则指向下一个sector。SAT可能在任意位置包含FreeSID(-1),这些sector将不被流使用。如果该位置包含EndOfChainSID(-2)表示一个流的结束。如果sector用于存放SAT则为SATSID(-3),同样用于存放MSAT则为MSATSID(-4)。一个SID链的起点从用户流的目录入口(directoryentry,见6.2节)或头(内部控制流)或目录流本身获得。例:一个复合文档包含一个用于存放SAT的sector(sector1)和2个流。Sector1的内容如下图:在位置1其值为-3,表明Sector1是SAT的一部分。其中一个流为内部目录流,假定头中指定其开始为Sector0,SAT中位置0的值为2,位置2的值为3,位置3的值为-2。因此目录流的SID链为[0,2,3,–2],即此目录流存放于3个sector中。目录中包含一个用户流的入口假定为sector10,从图中可看出此流的SID链为[10,6,7,8,9,–2]。第五章短流5.1短流存放流当一个流的大小小于指定的值(在头中指定),就称为短流(short-stream)。短流并不是直接使用sector存放数据,而是内含在一种特殊的内部控制流——短流存放流(short-streamcontainerstream)中。短流存放流象其他的用户流一样:先从目录中的根仓库入口(rootstorageentry)获得第一个使用的sector,其SID链从SAT中获得。然后此流将其所占用的sectors分成short-sector,以便用来存放短流。此处也许较难理解,我们来打个比方:既然流组成符合文档,而短流组成短流存放流,这两者是相似的。把短流存放流当作复合文档,那么短流对应流,short-sector对应sector,唯一的不同是复合文档有一个头结构,而短流存放流没有。short-sector的大小在头中已经指定,因此可根据SID计算short-sector相对于短流存放流的偏移量(offset)。公式为:short_s_pos(SID)=SID?short_s_size=SID?2sssz例:sssz=6andSID=5:short_s_pos(SID)=SID?2sssz=5?26=5?64=320.5.2短扇区配置表短扇区配置表(SSAT:short-sectorallocationtable)是一个SID数组,包含所有短流的SID链。与SAT很相似。用于存放SSAT的第一个sector的SID在头中指定,其余的SID链从SAT中获得。存放SSAT的sector的内容:(s_size表示sector的大小)OffsetSizeContents0s_sizeSSAT的s_size/4个SID的数组SSAT的用法与SAT类似,不同的是其SID链引用的是short-sector。第六章目录6.1目录结构目录(directory)是一种内部控制流,由一系列目录入口(directoryen
本文标题:复合文档的二进制存储格式
链接地址:https://www.777doc.com/doc-6682854 .html