程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> COM原理及應用---- 結構化存儲

COM原理及應用---- 結構化存儲

編輯:關於C++

1、結構化存儲

COM的結構化存儲(structured storage)機制,也稱為永久存儲(persistent storage)機制。結構化存儲可以說是軟件存儲技術的一個重要進展,COM針對組件軟件的需要,在文件系統的基礎上,提出了結構化存儲的概念。利用結構化存儲,組件程序之間可很好地協同工作,一個組件程序可以與另一個組件程序共享同一個文件,就如同一個應用程序與另一個應用程序共享同一個磁盤文件系統一樣。

COM定義了結構化存儲的規范,包括一組接口和實現這些接口成員函數的一些規則;同時COM也提供了結構化存儲的實現,即復合文檔技術。復合文檔技術是 OLE的基礎。OLE最初的目標是在文檔中嵌入或鏈接對象,當然現在OLE的發展已經超出了這個范圍,但復合文檔仍然是OLE的基礎存儲技術。

2、結構化存儲的引入

組件化程序設計方法把應用系統設計成多個組件程序,如何在這些組件程序之間以共享方式訪問同一個文件是組件化程序設計必須要解決的問題。而多個組件通過文件句柄訪問共享文件難以實現,結構化存儲技術“借用”文件系統的概念,在文件內部構造了一個類似於文件系統的樹狀層次結構,解決了這一問題。

結構化存儲的層次結構的節點可以是兩種對象:存儲對象和流對象,每個存儲對象或者流對象都是一個可獨立進行讀寫操作的對象,組件程序只對它擁有的節點對象進行操作。從應用系統整體上看,這些組件程序在共享訪問同一個文件。

3、文件系統

操作系統的誕生把應用程序與底層存儲設備隔離開來,操作系統為應用程序的運行提供了基本的抽象環境,它可以處理所有與存儲設備有關的基本操作。同時,操作系統引入了文件系統的概念,允許多個應用程序共享同一個存儲設備。而且,操作系統為應用程序提供了一種抽象的流式存儲結構,應用程序仍然獨立地訪問它自己的存儲空間,不同應用程序相互之間不受干擾。

4、文件系統與結構化存儲的框圖

5、存儲對象和流對象

對於一個完整的存儲操作來說,它被分為兩個層次:應用程序調用API函數;操作系統提供API函數的實現。COM庫提供了結構化存儲的實現,它提供了一組接口和API函數供組件程序調用來完成實際的存儲操作。因此,結構化存儲定義的存儲對象和流對象由COM庫實現,應用程序或者組件程序並不需要實現這兩個對象,就好比應用程序不需要實現文件句柄或者目錄對象一樣。

流對象非常類似於單獨的磁盤文件,它也是進行數據讀寫操作的基本對象,利用流對象可以保存各種類型的數據,它有自身的訪問權限和一個獨立的搜索指針。流對象也用一個字符串作為其名稱,就好像文件名一樣。流對象是一個由COM實現的組件對象,它實現了基本的COM接口IStream,應用程序通過 IStream接口訪問流對象,進行各種數據訪問操作。

存儲對象類似於目錄對象,它也有一個字符串名稱,但它本身並沒有存儲數據信息,它作為其子存儲對象和子流對象的容器,只記錄了這些子對象的信息。存儲對象暴露IStorage接口,客戶程序通過IStorage接口對存儲對象進行操作。

應用程序或者組件程序可以通過結構化存儲機制共享同一個復合文件,存儲對象和流對象也可以在這些程序之間被共享訪問,即使這些程序運行在不同的進程中。

6、結構化存儲特性――訪問模式

存儲對象和流對象支持兩種基本的訪問模式:直接訪問和事務訪問模式。在直接訪問模式下,程序對存儲對象或者流對象的修改操作馬上生效;而在事務模式下,程序對存儲對象或者流對象所作的修改被緩存起來,只有當提交(Commit)時才真正有效,如果調用Revert成員函數,則可以恢復到上次提交或剛打開時的狀態。

7、結構化存儲特性――事務機制

在結構化存儲的樹狀層次結構中,事務特性可以適用於所有層次上的對象,因此,事務特性可以嵌套使用。

事務機制需要消耗較多系統資源。

8、結構化存儲特性――命名規則

在結構化存儲的樹狀層次結構中,每個存儲對象和流對象都有一個字符串名字。

根存儲對象的名字實際上就是復合文檔的文件名,所以根存儲對象的命名規則受文件系統影響,它遵守文件系統的命名約定。與創建和打開根存儲對象有關的函數中,直接使用文件名即可。所有非根存儲對象和流對象都由它們的父對象管理,由於它們存在於文件內部,因此它們的命名規則遵守COM給出的約定。

9、結構化存儲特性――增量訪問

增量訪問的意義在於減少了保存和打開文件時的操作時間和降低了應用程序對系統資源的要求。

對於大的復合文件的編輯操作,內存往往是個瓶頸,結構化存儲本身也需要消耗一些系統內存資源,但它實現的增量訪問反而降低了應用程序對內存的要求,同時也提高了系統的性能。

結構化存儲也帶來了另一個問題,那就是空間回收的管理。頻繁地對同一個復合文件進行修改、保存,則文件的尺寸總是在增長,原因在於刪除對象時,COM只是把這些所占用的磁盤空間標記為“未用”,而沒有釋放這些磁盤空間。當然COM以後可能會重用這些空間,但在重用之前,這些空間仍保留在文件中。解決這個問題的方法是:首先創建一個新的復合文件,然後調用原先根存儲對象的CopyTo函數,把以前的樹結構復制到新的根存儲中,則新的復合文件沒有碎片空間。

Microsoft Access或Word產生的文件就會出現這種情況。

10、結構化存儲實現:復合文檔

從結構化存儲的對象結構可以看出,要在特定的系統平台上實現結構化存儲,關鍵在兩方面:一是如何把根存儲與底層存儲介質結合起來,二是實現存儲對象和流對象。

復合文檔通過一個被稱為“LockBytes”的對象,把根存儲與底層的存儲介質聯系起來,其他的子對象則通過根存儲與底層存儲介質進行數據通信,從而實現了整個結構化存儲體系結構。底層介質不僅可以是磁盤文件,復合文檔也允許是內存空間,甚至是用戶自定義的虛擬空間。LockBytes對象實際上是所有存儲介質的一種抽象表達方式,它把存儲介質描述成一般化的字節序列,不管是磁盤文件還是內存區域都可以按字節序列對待。

COM庫提供了缺省的基於文件句柄操作的LockBytes對象,我們可以利用此 LockBytes對象建立復合文件。COM庫還提供了基於內存的LockBytes對象,我們可以利用內存LockBytes對象建立內存中的復合文檔。而且,COM還允許我們實現自己的LockBytes對象,並在自定義LockBytes對象的基礎上建立復合文檔。

11、復合文檔API函數

創建復合文檔API函數:StgCreateDocfile和StgCreateDocfileOnLockBytes。

打開已經存在的復合文檔API函數:StgOpenStorage和StgOpenStorageOnLockBytes。

在內存基礎上創建LockBytes對象或者流對象的API函數:CreateILockBytesOnHGlobal、 GetHGlobalFromILockBytes、CreateStreamOnHGlobal、GetHGlobalFromStream。

其他的API函數:StgIsStorageFile和StgSetTimes。

12、零內存保存特性和IRootStorage接口

復合文檔通過LockBytes對象把根存儲對象與底層的文件操作隔離開來,所以我們在訪問存儲對象或者流對象時避開了文件句柄操作。當我們用事務方式打開復合文件時,COM實際上用到了三個文件句柄,一個是復合文件句柄,另一個是臨時文件句柄,該臨時文件記錄了存儲對象操作過程中的修改信息,還有一個句柄用作在零內存情況下保存文件時預分配的文件句柄。

13、存儲對象、流對象和文件的CLSID信息

通過IStorage接口的SetClass函數可以為一個存儲對象賦一個CLSID標識符,並可通過Stat函數獲取此CLSID值。實際上,存儲對象通過此CLSID值把它與一段可執行代碼聯系起來,當客戶程序希望執行與存儲對象相聯系的代碼時,它利用CLSID值,並調用 CoCreateInstamce函數創建一個COM對象,再把存儲對象交給COM對象,由它處理存儲對象。這樣的COM對象稱為永久對象(persistent object),它通常實現了IPersist***接口,比如IPersistFile、IPersistStorage、 IPersistStream和IPersistStreamInit等,客戶程序通過這些接口進行數據交換。

COM也提供了幾個API函數用於存儲對象或者流對象執行與CLSID有關的一些常規操作:

(1)WriteClassStg和ReadClassStg函數封裝了 IStorage::SetClass和IStorage::Stat成員函數,可以完成存儲對象的CLSID的設置和獲取操作。存儲對象只是個容器,它本身不包含數據信息,所以它的CLSID信息被寫在其下面的一個子流對象中,其名字為“x01CompObj”。

(2)WriteClassStm和ReadClassStm函數使用一致的格式在流對象的當前位置分別寫或者讀CLSID信息,通常情況下,我們在流的起始處放置CLSID信息。

(3)GetClassFile函數返回一個與給定文件相聯系的CLSID。Windows桌面環境利用它把數據文件與應用程序聯系起來,實現了桌面環境中的數據驅動機制。

對於非復合文檔,Windows提供了兩種方法可以建立這樣的聯系。

(1)Windows系統注冊記錄了文件擴展名與ProgID之間的聯系,而ProgID又指定了CLSID,所以該文件擴展名與CLSID聯系起來了。

(2)Windows系統注冊表提供了一些文件匹配規則,在HKEY_CLASSES_ROOTFilType鍵下記錄了一些CLSID與它們的匹配規則。

14、復合文檔與結構化存儲

結構化存儲是COM規范的一部分,它描述了一個理想的存儲機制,而復合文檔作為它在Windows平台上的實現,它利用操作系統的特點增加了一些新的特性,但也不可避免地受到一些限制。復合文檔是目前Windows平台上的基本存儲機制。

15、永久接口

客戶程序通過永久接口維護永久對象的狀態信息,而狀態信息可以被存放在各種介質中,比如存儲對象、流對象或者文件中,根據介質的不同,COM定義了四個常用的永久接口:IPersistFile、IPersistStorage、IPersistStream和IPersistStreamInit,它們都派生自基本的IPersist接口。客戶程序可以向永久對象請求這些接口,然後通過接口讀寫對象的狀態信息。

16、永久對象的存儲特性

永久對象通過三種介質保存狀態數據,分別為流對象、存儲對象和文件。永久對象在三種介質上保存狀態數據的特性是不同的,操作過程也是不同的。

實際上,一個永久對象可以實現多個永久接口以便提供多種介質的存儲支持。從程序實現來講,這是一個多接口支持問題,從客戶程序來講,它只能使用一種接口,根據客戶程序的特性,它可以優先選擇一個永久接口。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved