13結(jié)構(gòu)化存儲(chǔ)_第1頁
13結(jié)構(gòu)化存儲(chǔ)_第2頁
13結(jié)構(gòu)化存儲(chǔ)_第3頁
13結(jié)構(gòu)化存儲(chǔ)_第4頁
13結(jié)構(gòu)化存儲(chǔ)_第5頁
已閱讀5頁,還剩16頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、十三. 結(jié)構(gòu)化存儲(chǔ)概念從文件系統(tǒng)到結(jié)構(gòu)化存儲(chǔ)存儲(chǔ)對(duì)象和流對(duì)象結(jié)構(gòu)化存儲(chǔ)特性復(fù)合文檔 結(jié)構(gòu)化存儲(chǔ)的實(shí)現(xiàn)LockBytes對(duì)象.創(chuàng)建基于內(nèi)存的復(fù)合文檔創(chuàng)建基于文件的復(fù)合文檔打開復(fù)合文檔復(fù)合文檔的CLSID永久對(duì)象例子: MFC實(shí)現(xiàn)永久對(duì)象例子:復(fù)合文檔11 概念1.1 文件系統(tǒng) 在操作系統(tǒng)誕生之前,應(yīng)用程序必須要處理底層的存儲(chǔ)設(shè)備驅(qū)動(dòng)。 操作系統(tǒng)引入了文件系統(tǒng)。把應(yīng)用系統(tǒng)和底層的存儲(chǔ)設(shè)備區(qū)分開來。多個(gè)應(yīng)用可以同時(shí)使用一個(gè)存儲(chǔ)設(shè)備。操作系統(tǒng)為應(yīng)用程序提供了抽象的流式的存儲(chǔ)結(jié)構(gòu)。 文件系統(tǒng)把存儲(chǔ)設(shè)備按照樹狀結(jié)構(gòu)重新組織起來。如UNIX的文件系統(tǒng),Windows文件系統(tǒng)。 根目錄,子目錄,文件。 目錄是

2、文件的容器。文件的數(shù)據(jù)可以存儲(chǔ)在不連續(xù)的存儲(chǔ)區(qū)域。操作系統(tǒng)會(huì)管理這些區(qū)域,用戶會(huì)以為訪問連續(xù)的空間。 操作系統(tǒng)提供了一組系統(tǒng)調(diào)用(Unix)或系統(tǒng)API(Windows)給應(yīng)用系統(tǒng)。應(yīng)用系統(tǒng)通過API來操作文件,從而操作存儲(chǔ)設(shè)備。 應(yīng)用系統(tǒng)使用文件描述符(Unix)或文件句柄(Windows)來代表打開的文件。多個(gè)應(yīng)用程序可以同時(shí)訪問一個(gè)文件。應(yīng)用系統(tǒng)需要采用同步機(jī)制來保證操作的一致性。事實(shí)上,這種處理很困難。2結(jié)構(gòu)化存儲(chǔ)把文件系統(tǒng)的概念引入到文件內(nèi)部。從而在存儲(chǔ)結(jié)構(gòu)上支持多應(yīng)用程序的并發(fā)訪問。主要思想:在文件內(nèi)部構(gòu)造一個(gè)樹狀層次結(jié)構(gòu)。由存儲(chǔ)對(duì)象和流對(duì)象構(gòu)成。根節(jié)點(diǎn)為根存儲(chǔ),根存儲(chǔ)下面可以有子

3、存儲(chǔ)或流對(duì)象。子存儲(chǔ)下面可以再有子存儲(chǔ)或流對(duì)象。存儲(chǔ)對(duì)象本身不包含信息,它是子存儲(chǔ)和流對(duì)象的容器。流對(duì)象是葉子節(jié)點(diǎn),是數(shù)據(jù)的載體。這種結(jié)構(gòu)稱為文件內(nèi)部的文件系統(tǒng),這樣的文件稱為復(fù)合文檔。結(jié)構(gòu)化存儲(chǔ)使得多用戶方便地并發(fā)訪問一個(gè)文件。各個(gè)應(yīng)用訪問屬于自己的存儲(chǔ)對(duì)象。部分訪問。增量訪問。1.2 從文件系統(tǒng)到結(jié)構(gòu)化存儲(chǔ)31.3 存儲(chǔ)對(duì)象和流對(duì)象 COM庫(kù)提供了結(jié)構(gòu)化存儲(chǔ)的實(shí)現(xiàn),它提供了一組接口和API函數(shù),應(yīng)用程序利用這些接口和函數(shù)來完成結(jié)構(gòu)化存儲(chǔ)操作。結(jié)構(gòu)化存儲(chǔ)定義的存儲(chǔ)對(duì)象和流對(duì)象由COM庫(kù)實(shí)現(xiàn),應(yīng)用程序不需要實(shí)現(xiàn)這兩個(gè)對(duì)象。流對(duì)象實(shí)現(xiàn)了IStream接口: class IStream:publi

4、c IUnkown (P207) Read, Write, Seek,CopyTo Commit 把所有變化提交到包容該流對(duì)象的存儲(chǔ)對(duì)象。 Revert rollback取消上次提交以來的所有操作。針對(duì)事務(wù)模式的流 存儲(chǔ)對(duì)象實(shí)現(xiàn)了 IStorage接口: class IStorage:public IUnkown (P208) CreateStream OpenStream 操作子流對(duì)象返回IStream接口指針 CreateStorage OpenStorage 操作子存儲(chǔ)對(duì)象,返回IStorage接口指針 EnumElements 枚舉所有的子流對(duì)象和子存儲(chǔ)對(duì)象。 commit Rever

5、t。針對(duì)事務(wù)模式的存儲(chǔ)。 Stat 獲取存儲(chǔ)對(duì)象的信息。41.4 結(jié)構(gòu)化存儲(chǔ)特性1.4.1 訪問模式 創(chuàng)建 臨時(shí)存儲(chǔ) 直接模式和事務(wù)模式 優(yōu)先 讀、寫權(quán)限 共享權(quán)限1.4.2 事務(wù)機(jī)制創(chuàng)建、打開存儲(chǔ)和流時(shí)可以指定事務(wù)模式。只有Commit后,所有的變化才提交到上級(jí)。revert可以恢復(fù)到上次commit以來的狀態(tài)。根存儲(chǔ)上commit則會(huì)寫到磁盤。revert會(huì)恢復(fù)創(chuàng)建、刪除、修改子對(duì)象到原先的狀態(tài)。事務(wù)可以嵌套。事務(wù)的嵌套以嵌套標(biāo)志為基礎(chǔ)而不完全取決與層次結(jié)構(gòu)。(中間層次可能不使用事務(wù))事務(wù)針對(duì)寫模式而不是讀模式事務(wù)的實(shí)現(xiàn)是在內(nèi)存中或臨時(shí)文件中保存文件拷貝的方式。所以消耗資源。在直接模式下,

6、revert操作沒有意義,commit操作僅僅對(duì)根存儲(chǔ)相當(dāng)于flush操作。在此模式下,我們不能假設(shè)所有的操作會(huì)馬上影響到文件系統(tǒng),修改有可能被緩存51.4.3 增量訪問減少保存和打開文件減少操作時(shí)間。必要時(shí)才訪問。降低了系統(tǒng)對(duì)資源的要求。1.4.4 注意事項(xiàng):必須從根存儲(chǔ)出發(fā)使用Open*或Create*逐個(gè)訪問才能到達(dá)底層。文件碎片。(調(diào)用根存儲(chǔ)CopyTo解決)62 復(fù)合文檔 結(jié)構(gòu)化存儲(chǔ)的實(shí)現(xiàn)2.1 LockBytes對(duì)象.實(shí)現(xiàn)結(jié)構(gòu)化存儲(chǔ): 1。根存儲(chǔ)與底層的存儲(chǔ)介質(zhì)結(jié)合 2。實(shí)現(xiàn)存儲(chǔ)對(duì)象和流對(duì)象。復(fù)合文檔(Compound Document)提供了“LockBytes”對(duì)象來實(shí)現(xiàn)根存儲(chǔ)

7、與底層介質(zhì)的聯(lián)系。底層介質(zhì)可以是磁盤文件、內(nèi)存或用戶自定義的虛擬空間。LockBytes對(duì)象是所有存儲(chǔ)介質(zhì)的一種抽象的表達(dá)方式。存儲(chǔ)介質(zhì)描述稱為一般化的字節(jié)流,LockBytes對(duì)象負(fù)責(zé)從字節(jié)流中讀取一批字節(jié),把一批字節(jié)寫到字節(jié)流中。 LockBytes對(duì)象實(shí)現(xiàn)了ILockBytes接口。這個(gè)接口只提供基本的讀寫操作。 COM庫(kù)提供了缺省的基于文件句柄的LockBytes對(duì)象??衫么藢?duì)象建立復(fù)合文件。COM提供了基于內(nèi)存的LockBytes對(duì)象,可利用此對(duì)象建立基于內(nèi)存的復(fù)合文檔。 COM允許應(yīng)用系統(tǒng)實(shí)現(xiàn)自定義的LockBytes對(duì)象,并建立復(fù)合文檔。 文件、內(nèi)存、任何可以抽象稱為字節(jié)序列的

8、存儲(chǔ)設(shè)備都可以作為復(fù)合文檔的載體。不同的載體可以使用統(tǒng)一的存儲(chǔ)結(jié)構(gòu),使用同樣的存儲(chǔ)對(duì)象和流對(duì)象。7復(fù)合文檔的模型LockBytesrootDisk其他Memory82.2 創(chuàng)建基于內(nèi)存的復(fù)合文檔從內(nèi)存句柄中創(chuàng)建內(nèi)存LockBytes對(duì)象:HGLOBAL GlobalAlloc( UINT uFlags, / allocation attributes SIZE_T dwBytes / number of bytes to allocate ); 分配內(nèi)存并返回內(nèi)存句柄然后使用:WINOLEAPI CreateILockBytesOnHGlobal (HGLOBAL hGlobal, /內(nèi)存句柄

9、BOOL fDeleteOnRelease, LPLOCKBYTES FAR* pplkbyt); /返回指針創(chuàng)建一個(gè)基于指定LockBytes對(duì)象創(chuàng)建一個(gè)復(fù)合文檔。WINOLEAPI StgCreateDoc( ILockBytes FAR *plkbyt,/ 底層LockBytes對(duì)象 DWORD grfMode, /訪問模式 DWORD reserved, IStorage * *ppstgOpen); /返回指針9使用缺省的基于文件句柄的LockBytes對(duì)象創(chuàng)建一個(gè)復(fù)合文檔。WINOLEAPI StgCreateDocfile( const OLECHAR FAR* pwcsName

10、, /復(fù)合文檔路徑 DWORD grfMode, /訪問模式 DWORD reserved, IStorage * *ppstgOpen);/返回指針2.3 創(chuàng)建基于文件的復(fù)合文檔102.4.1 打開文件復(fù)合文檔:WINOLEAPI StgOpenStorage( const OLECHAR FAR* pwcsName, /復(fù)合文檔路徑 IStorage FAR *pstgPriority, /原先打開的復(fù)合文檔 DWORD grfMode, SNB snbExclude, DWORD reserved, IStorage FAR * FAR *ppstgOpen); /返回指針 2.4.2

11、打開內(nèi)存復(fù)合文檔:WINOLEAPI StgOpenStorageOnILockBytes( ILockBytes FAR *plkbyt, / 底層LockBytes對(duì)象 IStorage FAR *pstgPriority, /原先打開的復(fù)合文檔 DWORD grfMode, SNB snbExclude, DWORD reserved, IStorage FAR * FAR *ppstgOpen); /返回指針2.4 打開復(fù)合文檔113 復(fù)合文檔的CLSIDWindows平臺(tái)上,文件與應(yīng)用程序相關(guān)聯(lián)Assosiation 1.通過后綴 Windows系統(tǒng)注冊(cè)表記錄了文件擴(kuò)展名和ProgI

12、D之間的聯(lián)系。而ProgID最終是與CLSID聯(lián)系在一起,從而確定可執(zhí)行應(yīng)用程序的。 手工操作方式:資源管理器工具文件夾選項(xiàng)文件類型 可以查看、修改、增加文件的Assosiation特性。也可以在注冊(cè)表中操作。2。如果后綴沒有匹配的,操作系統(tǒng)會(huì)看文件是否是復(fù)合文檔,(StgIsStorageFile函數(shù) 見p221),如果不是則要求手工選取可執(zhí)行應(yīng)用程序。如果是,則會(huì)讀取文檔的相關(guān)聯(lián)的CLSID。 WriteClassStg和ReadClassStg完成存儲(chǔ)對(duì)象的關(guān)聯(lián)CLSID的設(shè)置和獲取工作。存儲(chǔ)對(duì)象的一個(gè)子流對(duì)象“x01CompObj”存儲(chǔ)CLSID。以上函數(shù)封裝了IStorage:Set

13、Class和IStorage:Stat成員函數(shù)。 WriteClassStm和ReadClassStm完成流對(duì)象的關(guān)聯(lián)CLSID的設(shè)置和獲取工作注意存儲(chǔ)對(duì)象、流對(duì)象的CLSID不是這兩個(gè)COM對(duì)象的CLSID而是,它們相關(guān)聯(lián)的可執(zhí)行應(yīng)用程序的CLSID。 124 永久對(duì)象概念上,永久對(duì)象與存儲(chǔ)對(duì)象和流對(duì)象其實(shí)沒有任何聯(lián)系。它只不過是一個(gè)COM對(duì)象,之所以稱為永久對(duì)象,是因?yàn)樗杏谰玫臓顟B(tài),它可以把狀態(tài)信息存儲(chǔ)下來,以后可以重建這樣的對(duì)象,并且恢復(fù)到以前的狀態(tài)。它之所以跟存儲(chǔ)對(duì)象和流對(duì)象在實(shí)際操作中有密切的聯(lián)系,那是因?yàn)椋覀兒芊奖愕厥褂肅OM的結(jié)構(gòu)化存儲(chǔ)機(jī)制來保存永久對(duì)象的狀態(tài)。其實(shí),我們完全

14、可以不使用結(jié)構(gòu)化存儲(chǔ)而使用別的方式實(shí)現(xiàn)永久對(duì)象,比如磁盤文件,系統(tǒng)注冊(cè)表,目錄服務(wù),數(shù)據(jù)庫(kù)服務(wù)等等。但是使用COM的結(jié)構(gòu)化存儲(chǔ)可以使得永久對(duì)象實(shí)現(xiàn)起來更方便,我們可以利用結(jié)構(gòu)化存儲(chǔ)的優(yōu)良特性。注意我們不能使用基于內(nèi)存的結(jié)構(gòu)化存儲(chǔ)機(jī)制來實(shí)現(xiàn)永久對(duì)象。因?yàn)閮?nèi)存不是“永久”的。COM定義了四個(gè)常用的永久接口。IPersistStorage, IPersistStream, IPersistStreamInit 和IPersistFile(接口定義見p225)所有的永久接口都包含三個(gè)基本的函數(shù)IsDirty Load Save,雖然參數(shù)各不相同,但含義都一樣。Load成員函數(shù)使得永久對(duì)象從存儲(chǔ)介質(zhì)中裝

15、入狀態(tài)數(shù)據(jù)。Save成員把狀態(tài)數(shù)據(jù)保存到介質(zhì)中。IsDirty反映了自上次保存后是否被修改,以讓客戶決定是否需要保存。前三個(gè)接口使用的結(jié)構(gòu)化存儲(chǔ)機(jī)制。后一個(gè)接口直接使用文件。135 MFC實(shí)現(xiàn)永久對(duì)象的例子(p229)1。MFC DLL Automation選項(xiàng)。2。新建一個(gè)類CTextObject派生自CCmdTarget,并使之稱為自動(dòng)化對(duì)象。(并沒有必要是自動(dòng)化對(duì)象,只是為了方便而已)3。為自動(dòng)化對(duì)象CTextObject增加屬性Text,類型為VARIANT 實(shí)現(xiàn)方式為Get/Set method 注意odl文件的變化,CTextObject類增加了兩個(gè)成員函數(shù)GetText 和Set

16、Text4。添加內(nèi)部成員變量m_pText 記錄內(nèi)部文本信息。5。添加接口IPersistStream支持/ 聲明接口嵌套類成員BEGIN_INTERFACE_PART(PersistStream, IPersistStream)STDMETHOD(GetClassID)(LPCLSID);STDMETHOD(IsDirty)();STDMETHOD(Load)(LPSTREAM);STDMETHOD(Save)(LPSTREAM, BOOL);STDMETHOD(GetSizeMax)(ULARGE_INTEGER FAR*);END_INTERFACE_PART(PersistStream

17、)/初始化接口映射表BEGIN_INTERFACE_MAP(CTextObject, CCmdTarget)INTERFACE_PART(CTextObject, IID_IPersistStream, PersistStream)INTERFACE_PART(CTextObject, IID_ITextObject, Dispatch)END_INTERFACE_MAP()永久對(duì)象一共實(shí)現(xiàn)了兩個(gè)接口IDispatch和IPersistStream。146.實(shí)現(xiàn)屬性GetText() SetText()7實(shí)現(xiàn)接口IPersistStream的成員函數(shù)(IUnkown的函數(shù)) AddRef Re

18、lease QueryInterfaceSTDMETHODIMP_(ULONG) CTextObject:XPersistStream:AddRef()METHOD_PROLOGUE(CTextObject, PersistStream) /得到與父類指針的偏移return (ULONG) pThis-ExternalAddRef();8實(shí)現(xiàn)接口IPersistStream的成員函數(shù)STDMETHODIMP CTextObject:XPersistStream:GetClassID(LPCLSID lpClassID)METHOD_PROLOGUE(CTextObject, PersistSt

19、ream)ASSERT_VALID(pThis);*lpClassID = CTextObject:guid; /由DECLARE_OLECREATE定義。供類廠COleClassFactory使用return NOERROR; / 是IPersist的函數(shù)。STDMETHODIMP CTextObject:XPersistStream:IsDirty()METHOD_PROLOGUE(CTextObject, PersistStream)ASSERT_VALID(pThis);return NOERROR; /采取了簡(jiǎn)化處理。15STDMETHODIMP CTextObject:XPersi

20、stStream:Load(LPSTREAM pStm) ULONG nLength; STATSTG statstg;METHOD_PROLOGUE(CTextObject, PersistStream)ASSERT_VALID(pThis);/得到父類指針if(pThis-m_pText != NULL) delete pThis-m_pText;/ 清空原有內(nèi)容VERIFY(pStm-Stat(&statstg, STATFLAG_NONAME) =NOERROR); /得到流的屬性int nSize = statstg.cbSize.LowPart; / assume 0) pThis

21、-m_pText = new charnSize;pStm-Read(pThis-m_pText, nSize, &nLength);/調(diào)用流的Read方法從流中讀取數(shù)據(jù)存到內(nèi)部成員中return NOERROR;此函數(shù)會(huì)被用戶調(diào)用,并輸入流指針作為參數(shù)。16STDMETHODIMP CTextObject:XPersistStream:Save(LPSTREAM pStm, BOOL fClearDirty)METHOD_PROLOGUE(CTextObject, PersistStream)ASSERT_VALID(pThis);int nSize = strlen(pThis-m_pTe

22、xt) + 1;pStm-Write(pThis-m_pText, nSize, NULL);/內(nèi)部數(shù)據(jù)存到流中。return NOERROR;STDMETHODIMP CTextObject:XPersistStream:GetSizeMax(ULARGE_INTEGER FAR* pcbSize)METHOD_PROLOGUE(CTextObject, PersistStream)ASSERT_VALID(pThis);pcbSize-LowPart = strlen(pThis-m_pText) + 1;/返回內(nèi)部數(shù)據(jù)的長(zhǎng)度pcbSize-HighPart = 0; / assume Release();19. VERIFY(pStg-CreateStorage(T2COLE(szStorageName), STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &pSubStg) = S_OK); /創(chuàng)建子存儲(chǔ)對(duì)象 ASSERT(pSubStg != NULL); ReadDirectory(szNewPath, pSubStg);/遞歸調(diào)用 pS

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論