ppt文檔數據恢復

Microsoft Office PowerPoint,是微軟公司設計的演示文稿軟體。用戶不僅可以在投影儀或者計算機上進行演示,也可以將演示文稿列印出來,製作成膠片,以便套用到更廣泛的領域中。利用Microsoft Office PowerPoint不僅可以創建演示文稿,還可以在網際網路上召開面對面會議、遠程會議或在網上給觀眾展示演示文稿。Microsoft Office PowerPoint做出來的東西叫演示文稿,它是一個檔案,其格式後綴名為:ppt、pptx;或者也可以保存為:pdf、圖片格式等。2010及以上版本中可保存為視頻格式。演示文稿中的每一頁就叫幻燈片,每張幻燈片都是演示文稿中既相互獨立又相互聯繫的內容。

ppt檔案屬於複合文檔結構,下面講解一下複合文檔的結構。

倉庫與流

複合文檔的原理就像一個檔案系統(檔案系統:如FAT與NTFS)。複合文檔將數據分成許多流(Streams),這些流又存儲在不同的倉庫(Storages)里。將複合文檔想像成你的D糟,D糟用的是NTFS(NT File System)格式,流就相當於D糟里的檔案,倉庫就相當於D糟里的資料夾。

流和倉庫的命名規則與檔案系統相似,同一個倉庫下的流及倉庫不能重名,不同倉庫下可以有同名的流。每個複合文檔都有一個根倉庫(root storage)。

扇區與扇區鏈

扇區與扇區標識

所有的流又分成更小的數據塊,叫做數據扇區(sectors)。Sectors 可能包含控制數據或用戶數據。

整個檔案由一個頭(Header)結構以及其後的所有Sectors組成。Sectors的大小在頭中確定,且每個Sectors的大小都相同。

以下為示意圖:

HEADER

SECTOR 0

SECTOR 1

SECTOR 2

SECTOR 3

SECTOR 4

SECTOR 5

SECTOR 6

Sectors 簡單的以其在檔案中的順序列舉,一個扇區的索引(從0開始)叫做扇區標識(SID:sector identifier)。SID是一個有符號的32位的整型值。

如果一個SID的值非負,就表示真正存在的那個Sector;如果為負,就表示特殊的含義。下表給出有效的特殊SID:

SID Name Meaning

–1 Free SID 空閒sector,可存在於檔案中,但不是任何流的組成部分。

–2 End Of Chain SID SID鏈的結束標記 (見2.2節)

–3 SAT SID 此Sector用於存放扇區配置表(SAT)(見4.2節)

–4 MSAT SID 此Sector用於存放主扇區配置表(MSAT)(見4.1節)

扇區鏈與扇區標識鏈

用於存儲流數據的所有Sectors的列表叫做扇區鏈(Sector Chain)。這些Sectors可以是無序的。因此用於指定一個流的Sectors的順序的SID數組就稱為SID chain。一個SID chain總是以End Of Chain SID(-2)為結束標記。

流的SID鏈是通過扇區配置表構建的(見4.2節),但短流和以下兩種內部流除外:

1.主扇區配置表,其從自身構建SID鏈(每個扇區包含下一個扇區的SID)。

2.扇區配置表,其通過主扇區配置表構建SID鏈。

複合文檔頭

複合文檔頭的內容

複合文檔頭在檔案的開始,且其大小必定為512位元組。這意味著第一個Sector的開始相對檔案的偏移量為512位元組 。

複合文檔頭的結構如下:

Offset Size Contents

0 8 複合文檔檔案標識:D0H CFH 11H E0H A1H B1H 1AH E1H

8 16 此檔案的唯一標識(不重要, 可全部為0)

24 2 檔案格式修訂號 (一般為003EH)

26 2 檔案格式版本號(一般為0003H)

28 2 位元組順序規則標識(見3.2)::FEH FFH = Little-Endian FFH FEH = Big-Endian

30 2 複合文檔中sector的大小(ssz),以2的冪形式存儲, sector實際大小為s_size=2ssz 位元組

(一般為9即512位元組, 最小值7即128位元組)

32 2 short-sector的大小(見5.1),以2的冪形式存儲, short-sector實際大

小為s_s_size = 2sssz 位元組(一般為6即64位元組,最大為sector的大小)

34 10 Not used

44 4 用於存放扇區配置表(SAT)的sector總數

48 4 用於存放目錄流的第一個sector的SID (見6)

52 4 Not used

56 4 標準流的最小大小(一般為4096 bytes), 小於此值的流即為短流。

60 4 用於存放短扇區配置表(SSAT)的第一個sector的SID (見5.2), 或為–2 (End Of Chain SID)如不存在。

64 4 用於存放短扇區配置表(SSAT)的sector總數

68 4 用於存放主扇區配置表(MSAT)的第一個sector的SID (見4.1), 或為–2 (End Of Chain SID) 若無附加的sectors。

72 4 用於存放主扇區配置表(MSAT)的sector總數

76 436 存放主扇區配置表(MSAT)的第一部分,包含109個SID。

位元組順序(Byte Order)

檔案數據的二進制存儲有兩種方法Little-Endian 和 Big-Endian,但實際套用中只使用Little-Endian方法即:低位8位元組存放在地址的低位,高位8位元組存放在地址的高位。

例:一個32位的整數13579BDFH(轉為十進制即324508639),以Little-Endian存放為DFH 9BH 57H13H,以Big-Endian 存放為 13H 57H 9BH DFH。(H下標表示十六進制)

扇區偏移量

從頭中的信息可以計算出一個sector的偏移量(offset),公式為:

sec_pos(SID) = 512 + SID ? s_size = 512 + SID ? 2 ssz

例:ssz = 10 and SID = 5:

sec_pos(SID) = 512 + SID ? 2 ssz = 512 + 5 ? 210 = 512 + 5 ? 1024 = 5632.

扇區配置

主扇區配置表

主扇區配置表(MSAT:master sector allocation table)是一個SID數組,指明了所有用於存放扇區配置表(SAT:sector allocation table)的sector的SID。MSAT的大小(SID個數)就等於存放SAT的sector數,在頭中指明。

MSAT的前109個SID也存放於頭中,如果一個MSAT的SID數多餘109個,那么多出來的SID將存放於sector中,頭中已經指明了用於存放MSAT的第一個sector的SID。在用於存放MSAT的sector中的最後一個SID指向下一個用於存放MSAT的sector,如果沒有下一個則為End Of Chain SID(-2)。

存放MSAT的sector的內容:(s_size表示sector的大小)

Offset Size Contents

0 s_size-4 MSAT的(s_size-4) / 4個SID的數組

s_size-4 4 下一個用於存放MSAT的sector的SID,或-2(已為最後一個)

最後一個存放MSAT的sector可能未被完全填滿,空閒的地方將被填上Free SID(-1)。

例:一個複合文檔需要300個sector用於存放SAT,頭中指定sector的大小為512位元組,這說明一個sector可存放128個SID。MAST有300個SID,前109個放於頭中,其餘的191個將要占用2個sector來存放。此例假定第一個存放MSAT的sector為sector 1,則sector 1包含127個SID。第128個SID指向一個用於存放MSAT的sector,假定為sector 6,則sector 6包含剩下的64個SID(最後一個SID為-2,其他的值為-1)。

扇區配置表

扇區配置表(SAT:sector allocation table)是一個SID數組,包含所有用戶流(短流除外)和內部控制流(the short-stream container stream, 見5.1, the short-sector allocation table, 見5.2, and the directory, 見7)的SID鏈。SAT的大小(SID個數)就等於複合文檔中所存在的sector的個數。

SAT的建立就是通過按順序讀取MSAT中指定的sector中的內容。

存放SAT的sector的內容:(s_size表示sector的大小)

Offset Size Contents

0 s_size SAT的s_size / 4個SID的數組

當通過SAT為一個流創建SID鏈時,SAT數組的當前位置(array index)表示的就是當前的sector,而該位置存放的SID則指向下一個sector。

SAT可能在任意位置包含Free SID(-1),這些sector將不被流使用。如果該位置包含End Of Chain SID(-2)表示一個流的結束。如果sector用於存放SAT則為SAT SID(-3),同樣用於存放MSAT則為MSAT SID(-4)。

一個SID鏈的起點從用戶流的目錄入口(directory entry,見6.2節)或頭(內部控制流)或目錄流本身獲得。

短流

短流存放流

當一個流的大小小於指定的值(在頭中指定),就稱為短流(short-stream)。 短流並不是直接使用sector存放數據,而是內含在一種特殊的內部控制流——短流存放流(short-stream container stream)中。

短流存放流象其他的用戶流一樣:先從目錄中的根倉庫入口(root storage entry)獲得第一個使用的sector,其SID鏈從SAT中獲得。然後此流將其所占用的sectors分成short-sector,以便用來存放短流。此處也許較難理解,我們來打個比方:既然流組成符合文檔,而短流組成短流存放流,這兩者是相似的。把短流存放流當作複合文檔,那么短流對應流,short-sector對應sector,唯一的不同是複合文檔有一個頭結構,而短流存放流沒有。short-sector的大小在頭中已經指定,因此可根據SID計算short-sector相對於短流存放流的偏移量(offset)。公式為:

short_s_pos(SID) = SID ? short_s_size = SID ? 2 sssz

例:sssz = 6 and SID = 5:

short_s_pos(SID) = SID ? 2 sssz = 5 ? 26 = 5 ? 64 = 320.

5.2 短扇區配置表

短扇區配置表(SSAT:short-sector allocation table)是一個SID數組,包含所有短流的SID鏈。與SAT很相似。

用於存放SSAT的第一個sector的SID在頭中指定,其餘的SID鏈從SAT中獲得。

存放SSAT的sector的內容:(s_size表示sector的大小)

Offset Size Contents

0 s_size SSAT的s_size / 4個SID的數組

SSAT的用法與SAT類似,不同的是其SID鏈引用的是short-sector。

目錄

目錄結構

目錄(directory)是一種內部控制流,由一系列目錄入口(directory entry)組成。每一個目錄入口都指向複合文檔的一個倉庫或流。目錄入口以其在目錄流中出現的順序被列舉,一個以0開始的目錄入口索引稱為目錄入口標識(DID: directory entry identifier)。

如下圖所示:

DIRECTORY ENTRY 0

DIRECTORY ENTRY 1

DIRECTORY ENTRY 2

DIRECTORY ENTRY 3

...

目錄入口的位置不因其指向的倉庫或流的存在與否而改變。如果一個倉庫或流被刪除了,其相應的目錄入口就標記為空。在目錄的開始有一個特殊的目錄入口,叫做根倉庫入口(root storage entry),其指向根倉庫。

目錄將每個倉庫的直接成員(倉庫或流)放在一個獨立的紅黑樹(red-black tree)中。紅黑樹是一種樹狀的數據結構,本文僅簡單介紹一下,詳細情況請參考有關資料。

建構一個Red-Black tree的規則:

1. 每個節點(node)的顏色屬性不是紅就是黑。

2. 根節點一定是黑的。

3. 如果某個節點是紅的,那它的子節點一定是黑的。

4. 從根節點到每個葉節點的路徑(path)必須有相同數目的黑節點。

ex: B (用圖形來解說第4點,從根節點

/ \ 到最底層的node,你會發現每個

B B path都恰好有3個black node)

/ \ / \

B B R B

/ / \ / \

R B B R R

/ \

R R

注意並不總是執行上述規則。安全的方法是忽略節點的顏色。

1.根倉庫入口描述根倉庫,它不是任何倉庫入口的成員,因此無需構建紅黑樹。

2.根倉庫的所有直接成員(“Storage1”, “Storage2”, “Stream1”, “Stream2”, “Stream3”, 和 “Stream4”)將組成一棵紅黑樹,其根節點的DID存放於根倉庫入口中。

3.倉庫Storage1隻有一個成員Stream1,Stream1構成一棵紅黑樹,此樹只有一個節點。Storage1的目錄入口包含Stream1的DID。

4. 倉庫Storage2包含3個成員“Stream21”, “Stream22”, 和“Stream23”。這3個成員將構建一棵紅黑樹,其根節點的DID存放於Storage2的目錄入口中。

這種存放規則將導致每個目錄入口都包含3個DID:

1.在包含此目錄入口的紅黑樹中,此目錄入口的左節點的DID。

2.在包含此目錄入口的紅黑樹中,此目錄入口的右節點的DID。

3.若此目錄入口表示一個倉庫,則還包含此倉庫的直接成員所組成的另一顆紅黑樹的根節點的DID。

在構建紅黑樹的過程中,一個節點究竟作為左還是右,是通過比較其名字來判斷的。一個節點比另一個小是指其名字的長度更短,如長度一樣,則逐字元比較。

規定:左節點<根節點<右節點。

目錄入口

一個目錄入口的大小嚴格地為128位元組,計算其相對目錄流的偏移量的公式為:dir_entry_pos(DID) = DID ? 128。

目錄入口的內容:

Offset Size Contents

0 64 此入口的名字(字元數組), 一般為16位的Unicode字元,

以0結束。(因此最大長度為31個字元)

64 2 用於存放名字的區域的大小,包括結尾的0。

(如:一個名字右5個字元則此值為(5+1)?2 = 12)

66 1 入口類型: 00H = Empty 03H = LockBytes (unknown) 01H = User storage

04H = Property (unknown) 02H = User stream 05H = Root storage

67 1 此入口的節點顏色: 00H = Red 01H = Black

68 4 其左節點的DID (若此入口為一個user storage or stream) 若沒有左節點就為-1。

72 4 其右節點的DID (若此入口為一個user storage or stream), 若沒有右節點就為-1。

76 4 其成員紅黑樹的根節點的DID (若此入口為storage), 其他為-1。

80 16 唯一標識符(若為storage)(不重要, 可能全為0)

96 4 用戶標記(不重要, 可能全為0)

100 8 創建此入口的時間標記。大多數情況都不寫。

108 8 最後修改此入口的時間標記。大多數情況都不寫。

116 4 若此為流的入口,指定流的第一個sector或short-sector的SID,若此為根倉庫入口,指定短流存放流的第一個sector的SID,

其他情況,為0。 120 4 若此為流的入口,指定流的大小(位元組)若此為根倉庫入口,指定短流存放流的大小

(位元組)其他情況,為0。

124 4 Not used

時間標記(time stamp) 是一個符號的64位的整數,表示從1601-01-01 00:00:00開始的時間值。此值的單位為10-7秒。

當計算時間標記是要注意閏年。

例:時間標記值為01AE408B10149C00H

計算步驟 公式 結果

轉為十進制 t0 = 121,105,206,000,000,000

化成秒的餘數 rfrac = t0 mod 107 rfrac = 0

化成秒的整數 t1 = t0 / 107 t1 = 12,110,520,600

化成分的餘數 rsec = t1 mod 60 rsec = 0

化成秒的整數 t2 = t1 / 60 t2 = 201,842,010

化成小時的餘數 rmin = t2 mod 60 rmin = 30

化成小時的整數 t3 = t2 / 60 t3 = 3,364,033

化成天的餘數 rhour = t3 mod 24 rhour = 1

化成天的整數 t4 = t3 / 24 t4 = 140,168

距1601-01-01的整年 ryear = 1601 + t4含的年 ryear = 1601 + 383 = 1984

到1984年還剩的天數 t5 = t4 – (1601-01-01 t5 = 140,168 – 139,887 = 281

到1984-01-01的天數)

距1984-01-01的月數 rmonth = 1 + t5含的月數 rmonth = 1 + 9 = 10

到10月還剩的天數 t6 = t5 – (1984-01-01 t6 = 281 – 274 = 7

到1984-10-01的天數)

10月最終天數 rday = 1 + t6 rday = 1 + 7 = 8

相關詞條

相關搜尋

熱門詞條

聯絡我們