15结构化存储_第1页
15结构化存储_第2页
15结构化存储_第3页
15结构化存储_第4页
15结构化存储_第5页
已阅读5页,还剩19页未读 继续免费阅读

下载本文档

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

文档简介

1、十五. 结构化存储概念从文件系统到结构化存储存储对象和流对象结构化存储特性复合文档 结构化存储的实现LockBytes对象.创建基于内存的复合文档创建基于文件的复合文档打开复合文档复合文档的CLSID永久对象例子: MFC实现永久对象例子:复合文档11 概念1.1 文件系统 在操作系统诞生之前,应用程序处理底层的存储设备。 操作系统引入了文件系统。把应用系统和底层的存储设备区分开来。多个应用可以同时使用一个存储设备。操作系统为应用程序提供了抽象的流式的存储结构。 文件系统把存储设备按照树状结构重新组织起来。如UNIX的文件系统,Windows文件系统。目录,文件。 目录是文件的容器。文件的数据

2、可以存储在不连续的存储区域。文件系统会管理这些区域。 操作系统提供了一组系统调用(Unix)或系统API(Windows)给应用系统。应用系统通过系统调用或API来操作文件,从而操作存储设备。 应用系统使用文件描述符(Unix)或文件句柄(Windows)来代表打开的文件。多个进程可以同时访问一个文件。这些进程需要采用同步机制来保证操作的一致性。事实上,这种处理很困难。2结构化存储把文件系统的概念引入到文件内部。从而在存储结构上支持多应用程序的并发访问。主要思想:在文件内部构造一个树状层次结构。由存储对象和流对象构成。根节点为根存储,根存储下面可以有子存储或流对象。子存储下面可以再有子存储或流

3、对象。存储对象本身不包含信息,它是子存储和流对象的容器。流对象是叶子节点,是数据的载体。这种结构称为文件内部的文件系统,这样的文件称为复合文档。Word Excel PowerPoint Visio 等文件都是复合文档。结构化存储使得多用户方便地并发访问一个文件。各个应用访问属于自己的存储对象。 部分访问。增量访问。1.2 从文件系统到结构化存储31.3 存储对象和流对象COM库提供了结构化存储的实现,它提供了一组接口和API函数,应用程序利用这些接口和函数来完成结构化存储操作。结构化存储定义的存储对象和流对象由COM库实现,应用程序不需要实现这两个对象。流对象实现了IStream接口: cl

4、ass IStream:public IUnknown (P207) Read, Write, Seek,CopyTo Commit 把所有变化提交到包容该流对象的存储对象。 Revert rollback取消上次提交以来的所有操作。针对事务模式的流 存储对象实现了 IStorage接口: class IStorage:public IUnknown (P208) CreateStream OpenStream 操作子流对象返回IStream接口指针 CreateStorage OpenStorage 操作子存储对象,返回IStorage接口指针 EnumElements 枚举所有的子流对象和

5、子存储对象。 commit Revert。针对事务模式的存储。 Stat 获取存储对象的信息。41.4 结构化存储特性1.4.1 访问模式 创建 临时存储 直接模式和事务模式 优先 读、写权限 共享权限51.4.2 事务机制创建、打开存储和流时可以指定事务模式。只有Commit后,所有的变化才提交到上级。revert可以恢复到上次commit以来的状态。根存储上commit则会写到磁盘。revert会恢复创建、删除、修改子对象到原先的状态。事务可以嵌套。事务的嵌套以嵌套标志为基础而不完全取决与层次结构。(中间层次可能不使用事务)事务针对写模式而不是读模式事务的实现是在内存中或临时文件中保存文件

6、拷贝的方式。所以消耗资源。在直接模式下,revert操作没有意义,commit操作仅仅对根存储相当于flush操作。在此模式下,我们不能假设所有的操作会马上影响到文件系统,修改有可能被缓存61.4.3 增量访问减少保存和打开文件减少操作时间。必要时才访问。降低了系统对资源的要求。1.4.4 注意事项:必须从根存储出发使用Open*或Create*逐个访问才能到达底层。文件碎片。(调用根存储CopyTo解决)72 复合文档 结构化存储的实现2.1 LockBytes对象.实现结构化存储:根存储与底层的存储介质结合实现存储对象和流对象。复合文档(Compound Document)提供 “Lock

7、Bytes”对象来实现根存储与底层介质的联系。底层介质可以是磁盘文件、内存或用户自定义的虚拟空间。LockBytes对象是所有存储介质的一种抽象的表达方式。存储介质描述称为一般化的字节流,LockBytes对象负责从字节流中读写字节。 LockBytes对象实现了ILockBytes接口以提供基本的读写操作。8COM库提供了缺省的基于文件句柄的LockBytes对象。可利用此对象建立复合文件。COM提供了基于内存的LockBytes对象,可利用此对象建立基于内存的复合文档。 COM允许应用系统实现自定义的LockBytes对象,并建立复合文档。 文件、内存、任何可以抽象称为字节序列的存储设备都

8、可以作为复合文档的载体。不同的载体可以使用统一的存储结构,使用同样的存储对象和流对象。9复合文档的模型LockBytesrootDisk其他Memory102.2 创建基于内存的复合文档从内存句柄中创建内存LockBytes对象:HGLOBAL GlobalAlloc( UINT uFlags, / 分配属性 SIZE_T dwBytes /字节数); 分配内存并返回内存句柄然后使用:WINOLEAPI CreateILockBytesOnHGlobal ( HGLOBAL hGlobal, /内存句柄 BOOL fDeleteOnRelease, LPLOCKBYTES FAR* pplkb

9、yt); /返回指针创建一个基于指定的LockBytes对象创建一个复合文档。WINOLEAPI StgCreateDoc( ILockBytes FAR *plkbyt,/ 底层LockBytes对象 DWORD grfMode, /访问模式 DWORD reserved, IStorage * *ppstgOpen); /返回指针11使用缺省的基于文件句柄的LockBytes对象创建一个复合文档。WINOLEAPI StgCreateDocfile( const OLECHAR FAR* pwcsName, /复合文档路径 DWORD grfMode, /访问模式 DWORD reserv

10、ed, IStorage * *ppstgOpen);/返回指针2.3 创建基于文件的复合文档122.4.1 打开文件复合文档:WINOLEAPI StgOpenStorage( const OLECHAR FAR* pwcsName, /复合文档路径 IStorage FAR *pstgPriority, /原先打开的复合文档 DWORD grfMode, SNB snbExclude, DWORD reserved, IStorage FAR * FAR *ppstgOpen); /返回指针 2.4.2 打开内存复合文档:WINOLEAPI StgOpenStorageOnILockByt

11、es( ILockBytes FAR *plkbyt, / 底层LockBytes对象 IStorage FAR *pstgPriority, /原先打开的复合文档 DWORD grfMode, SNB snbExclude, DWORD reserved, IStorage FAR * FAR *ppstgOpen); /返回指针2.4 打开复合文档133 复合文档的CLSIDWindows平台上,文件与应用程序相关联Assosiation 1.通过后缀 Windows系统注册表记录了文件扩展名和ProgID之间的联系。而ProgID最终是与CLSID联系在一起,从而确定可执行应用程序的。

12、手工操作方式:资源管理器工具文件夹选项文件类型 可以查看、修改、增加文件的Assosiation特性。也可以在注册表中操作。2。如果后缀没有匹配的,操作系统会看文件是否是复合文档,(StgIsStorageFile函数 见p221),如果不是则要求手工选取可执行应用程序。如果是,则会读取文档的相关联的CLSID。 WriteClassStg和ReadClassStg完成存储对象的关联CLSID的设置和获取工作。存储对象的一个子流对象“x01CompObj”存储CLSID。以上函数封装了IStorage:SetClass和IStorage:Stat成员函数。 WriteClassStm和Read

13、ClassStm完成流对象的关联CLSID的设置和获取工作注意存储对象、流对象的CLSID不是这两个COM对象的CLSID而是,它们相关联的可执行应用程序的CLSID。 144 永久对象概念上,永久对象与存储对象和流对象其实没有任何联系。它只不过是一个COM对象,之所以称为永久对象,是因为它有永久的状态,它可以把状态信息存储下来,以后可以重建这样的对象,并且恢复到以前的状态。它之所以跟存储对象和流对象在实际操作中有密切的联系,那是因为,我们很方便地使用COM的结构化存储机制来保存永久对象的状态。其实,我们完全可以不使用结构化存储而使用别的方式实现永久对象,比如磁盘文件,系统注册表,目录服务,数

14、据库服务等等。但是使用COM的结构化存储可以使得永久对象实现起来更方便,我们可以利用结构化存储的优良特性。注意我们不能使用基于内存的结构化存储机制来实现永久对象。因为内存不是“永久”的。15COM定义了四个常用的永久接口。IPersistStorage, IPersistStream, IPersistStreamInit 和IPersistFile(接口定义见p225)所有的永久接口都包含三个基本的函数IsDirty Load Save,虽然参数各不相同,但含义都一样。Load成员函数使得永久对象从存储介质中装入状态数据。Save成员把状态数据保存到介质中。IsDirty反映了自上次保存后是

15、否被修改,以让客户决定是否需要保存。前三个接口使用的结构化存储机制。后一个接口直接使用文件。165 MFC实现永久对象的例子(p229)1。MFC DLL Automation选项。2。新建一个类CTextObject派生自CCmdTarget,并使之称为自动化对象。(并没有必要是自动化对象,只是为了方便而已)3。为自动化对象CTextObject增加属性Text,类型为VARIANT 实现方式为Get/Set method 注意odl文件的变化,CTextObject类增加了两个成员函数GetText 和SetText4。添加内部成员变量m_pText 记录内部文本信息。5。添加接口IPer

16、sistStream支持/ 声明接口嵌套类成员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)/初始化接口映射表BEGIN_INTERFACE_MAP(CTextObject

17、, CCmdTarget)INTERFACE_PART(CTextObject, IID_IPersistStream, PersistStream)INTERFACE_PART(CTextObject, IID_ITextObject, Dispatch)END_INTERFACE_MAP()永久对象一共实现了两个接口IDispatch和IPersistStream。176.实现属性GetText() SetText()7实现接口IPersistStream的成员函数(IUnknown的函数) AddRef Release QueryInterfaceSTDMETHODIMP_(ULONG)

18、 CTextObject:XPersistStream:AddRef()METHOD_PROLOGUE(CTextObject, PersistStream) /得到与父类指针的偏移return (ULONG) pThis-ExternalAddRef();8实现接口IPersistStream的成员函数STDMETHODIMP CTextObject:XPersistStream:GetClassID(LPCLSID lpClassID)METHOD_PROLOGUE(CTextObject, PersistStream)ASSERT_VALID(pThis);*lpClassID = CT

19、extObject:guid; /由DECLARE_OLECREATE定义。供类厂COleClassFactory使用return NOERROR; / 是IPersist的函数。STDMETHODIMP CTextObject:XPersistStream:IsDirty()METHOD_PROLOGUE(CTextObject, PersistStream)ASSERT_VALID(pThis);return NOERROR; /采取了简化处理。18STDMETHODIMP CTextObject:XPersistStream:Load(LPSTREAM pStm) ULONG nLeng

20、th; STATSTG statstg;METHOD_PROLOGUE(CTextObject, PersistStream)ASSERT_VALID(pThis);/得到父类指针if(pThis-m_pText != NULL) delete pThis-m_pText;/ 清空原有内容VERIFY(pStm-Stat(&statstg, STATFLAG_NONAME) =NOERROR); /得到流的属性int nSize = statstg.cbSize.LowPart; / assume 0) pThis-m_pText = new charnSize;pStm-Read(pThis

21、-m_pText, nSize, &nLength);/调用流的Read方法从流中读取数据存到内部成员中return NOERROR;此函数会被用户调用,并输入流指针作为参数。19STDMETHODIMP CTextObject:XPersistStream:Save(LPSTREAM pStm, BOOL fClearDirty)METHOD_PROLOGUE(CTextObject, PersistStream)ASSERT_VALID(pThis);int nSize = strlen(pThis-m_pText) + 1;pStm-Write(pThis-m_pText, nSize,

22、 NULL);/内部数据存到流中。return NOERROR;STDMETHODIMP CTextObject:XPersistStream:GetSizeMax(ULARGE_INTEGER FAR* pcbSize)METHOD_PROLOGUE(CTextObject, PersistStream)ASSERT_VALID(pThis);pcbSize-LowPart = strlen(pThis-m_pText) + 1;/返回内部数据的长度pcbSize-HighPart = 0; / assume Release();22. VERIFY(pStg-CreateStorage(T2COLE(szStorageName), STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &pSubStg) = S_OK); /创建子存储对象 ASSERT(pSubStg != NULL); ReadDirectory(szNewPath, pSubStg);/递归调用 pSubSt

温馨提示

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

评论

0/150

提交评论