15结构化存储

上传人:sx****84 文档编号:243419094 上传时间:2024-09-22 格式:PPT 页数:24 大小:85KB
返回 下载 相关 举报
15结构化存储_第1页
第1页 / 共24页
15结构化存储_第2页
第2页 / 共24页
15结构化存储_第3页
第3页 / 共24页
点击查看更多>>
资源描述
单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,十五. 结构化存储,概念,从文件系统到结构化存储,存储对象和流对象,结构化存储特性,复合文档 结构化存储的实现,LockBytes,对象.,创建基于内存的复合文档,创建基于文件的复合文档,打开复合文档,复合文档的,CLSID,永久对象,例子:,MFC,实现永久对象,例子:复合文档,1,1 概念,1.1 文件系统,在操作系统诞生之前,应用程序处理底层的存储设备。,操作系统引入了文件系统。把应用系统和底层的存储设备区分开来。多个应用可以同时使用一个存储设备。操作系统为应用程序提供了抽象的流式的存储结构。,文件系统把存储设备按照树状结构重新组织起来。如,UNIX,的文件系统,,Windows,文件系统。,目录,文件。,目录是文件的容器。文件的数据可以存储在不连续的存储区域。文件系统会管理这些区域。 操作系统提供了一组系统调用(,Unix),或系统,API(Windows),给应用系统。应用系统通过系统调用或,API,来操作文件,从而操作存储设备。,应用系统使用文件描述符(,Unix),或文件句柄(,Windows),来代表打开的文件。,多个进程可以同时访问一个文件。这些进程需要采用同步机制来保证操作的一致性。事实上,这种处理很困难。,2,结构化存储把文件系统的概念引入到文件内部。从而在存储结构上支持多应用程序的并发访问。,主要思想:在文件内部构造一个树状层次结构。由,存储,对象和,流,对象构成。根节点为根存储,根存储下面可以有子存储或流对象。子存储下面可以再有子存储或流对象。存储对象本身不包含信息,它是子存储和流对象的容器。流对象是叶子节点,是数据的载体。这种结构称为文件内部的文件系统,这样的文件称为,复合文档,。,Word Excel PowerPoint Visio,等文件都是复合文档。,结构化存储使得多用户方便地并发访问一个文件。各个应用访问属于自己的存储对象。 部分访问。增量访问。,1.2 从文件系统到结构化存储,3,1.3 存储对象和流对象,COM,库提供了结构化存储的实现,它提供了一组接口和,API,函数,应用程序利用这些接口和函数来完成结构化存储操作。结构化存储定义的存储对象和流对象由,COM,库实现,应用程序不需要实现这两个对象。,流对象实现了,IStream,接口:,class IStream:public IUnknown (P207),Read, Write, Seek,CopyTo,Commit,把所有变化提交到包容该流对象的存储对象。,Revert rollback,取消上次提交以来的所有操作。针对事务模式的流,存储对象实现了,IStorage,接口:,class IStorage:public IUnknown (P208),CreateStream OpenStream,操作子流对象返回,IStream,接口指针,CreateStorage OpenStorage,操作子存储对象,返回,IStorage,接口指针,EnumElements,枚举所有的子流对象和子存储对象。,commit Revert。,针对事务模式的存储。,Stat,获取存储对象的信息。,4,1.4 结构化存储特性,1.4.1,访问模式,创建,临时存储,直接模式和事务模式,优先,读、写权限,共享权限,5,1.4.2 事务机制,创建、打开存储和流时可以指定事务模式。,只有,Commit,后,所有的变化才提交到上级。,revert,可以恢复到上次,commit,以来的状态。,根存储上,commit,则会写到磁盘。,revert,会恢复创建、删除、修改子对象到原先的状态。,事务可以嵌套。,事务的嵌套以嵌套标志为基础而不完全取决与层次结构。(中间层次可能不使用事务),事务针对写模式而不是读模式,事务的实现是在内存中或临时文件中保存文件拷贝的方式。所以消耗资源。,在直接模式下,,revert,操作没有意义,,commit,操作仅仅对根存储相当于,flush,操作。在此模式下,我们不能假设所有的操作会马上影响到文件系统,修改有可能被缓存,6,1.4.3 增量访问,减少保存和打开文件减少操作时间。必要时才访问。,降低了系统对资源的要求。,1.4.4 注意事项:,必须从根存储出发使用,Open*,或,Create*,逐个访问才能到达底层。,文件碎片。(调用根存储,CopyTo,解决),7,2 复合文档 结构化存储的实现,2.1,LockBytes,对象.,实现结构化存储:,根存储与底层的存储介质结合,实现存储对象和流对象。,复合文档(,Compound Document),提供 “,LockBytes,”,对象来实现根存储与底层介质的联系。底层介质可以是磁盘文件、内存或用户自定义的虚拟空间。,LockBytes,对象是所有存储介质的一种抽象的表达方式。存储介质描述称为一般化的字节流,,LockBytes,对象负责从字节流中读写字节。,LockBytes,对象实现了,ILockBytes,接口以提供基本的读写操作。,8,COM,库提供了,缺省的,基于,文件句柄,的,LockBytes,对象。可利用此对象建立复合文件。,COM,提供了基于,内存,的,LockBytes,对象,可利用此对象建立基于内存的复合文档。,COM,允许应用系统实现自定义的,LockBytes,对象,并建立复合文档。 文件、内存、任何可以抽象称为字节序列的存储设备都可以作为复合文档的载体。不同的载体可以使用统一的存储结构,使用同样的存储对象和流对象。,9,复合文档的模型,LockBytes,root,Disk,其他,Memory,10,2.2,创建基于内存的复合文档,从内存句柄中创建内存,LockBytes,对象:,HGLOBAL,GlobalAlloc,( UINT,uFlags, /,分配属性,SIZE_T,dwBytes,/,字节数,);,分配内存并返回,内存句柄,然后使用:,WINOLEAPI,CreateILockBytesOnHGlobal,( HGLOBAL,hGlobal,/,内存句柄,BOOL,fDeleteOnRelease,LPLOCKBYTES FAR*,pplkbyt,);,/,返回指针,创建一个基于指定的,LockBytes,对象创建一个复合文档。,WINOLEAPI,StgCreateDoc,(,ILockBytes,FAR *,plkbyt,/,底层,LockBytes,对象,DWORD,grfMode,/,访问模式,DWORD reserved,IStorage,* *,ppstgOpen,);,/,返回指针,11,使用缺省的基于文件句柄的,LockBytes,对象创建一个复合文档。,WINOLEAPI StgCreateDocfile(,const OLECHAR FAR* pwcsName, /,复合文档路径,DWORD grfMode, /,访问模式,DWORD reserved,IStorage * *ppstgOpen);/,返回指针,2.3,创建基于文件的复合文档,12,2.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 StgOpenStorageOnILockBytes(,ILockBytes FAR *plkbyt, /,底层,LockBytes,对象,IStorage FAR *pstgPriority, /,原先打开的复合文档,DWORD grfMode,SNB snbExclude,DWORD reserved,IStorage FAR * FAR *ppstgOpen); /,返回指针,2.4,打开复合文档,13,3 复合文档的,CLSID,Windows,平台上,文件与应用程序相,关联,Assosiation,1.,通过后缀,Windows,系统注册表记录了文件扩展名和,ProgID,之间的联系。而,ProgID,最终是与,CLSID,联系在一起,从而确定可执行应用程序的。,手工操作方式:资源管理器工具文件夹选项文件类型,可以查看、修改、增加文件的,Assosiation,特性。也可以在注册表中操作。,2。如果后缀没有匹配的,操作系统会看文件是否是复合文档,(,StgIsStorageFile,函数 见,p221),,如果不是则要求手工选取可执行应用程序。如果是,则会读取文档的相关联的,CLSID。,WriteClassStg,和,ReadClassStg,完成存储对象的关联,CLSID,的设置和获取工作。存储对象的一个子流对象“,x01CompObj”,存储,CLSID。,以上函数封装了,IStorage:SetClass,和,IStorage:Stat,成员函数。,WriteClassStm,和,ReadClassStm,完成流对象的关联,CLSID,的设置和获取工作,注意存储对象、流对象的,CLSID,不是这两个,COM,对象的,CLSID,而是,它们相关联的可执行应用程序的,CLSID。,14,4 永久对象,概念上,永久对象与存储对象和流对象其实没有任何联系。,它只不过是一个,COM,对象,之所以称为永久对象,是因为它有永久的状态,它可以把状态信息存储下来,以后可以重建这样的对象,并且恢复到以前的状态。它之所以跟存储对象和流对象在实际操作中有密切的联系,那是因为,我们很方便地使用,COM,的结构化存储机制来保存永久对象的状态。其实,我们完全可以不使用结构化存储而使用别的方式实现永久对象,比如磁盘文件,系统注册表,目录服务,数据库服务等等。,但是使用,COM,的结构化存储可以使得永久对象实现起来更方便,我们可以利用结构化存储的优良特性。,注意我们不能使用基于内存的结构化存储机制来实现永久对象。因为内存不是“永久”的。,15,COM,定义了四个常用的永久接口。,IPersistStorage, IPersistStream, IPersistStreamInit,和,IPersistFile(,接口定义见,p225),所有的永久接口都包含三个基本的函数,IsDirty Load Save,,虽然参数各不相同,但含义都一样。,Load,成员函数使得永久对象从存储介质中装入状态数据。,Save,成员把状态数据保存到介质中。,IsDirty,反映了自上次保存后是否被修改,以让客户决定是否需要保存。,前三个接口使用的结构化存储机制。后一个接口直接使用文件。,16,5 MFC,实现永久对象的例子(,p229),1。,MFC DLL Automation,选项。,2。新建一个类,CTextObject,派生自,CCmdTarget,,并使之称为自动化对象。(并没有必要是自动化对象,只是为了方便而已),3。为自动化对象,CTextObject,增加属性,Text,,类型为,VARIANT,实现方式为,Get/Set method,注意,odl,文件的变化,,CTextObject,类增加了两个成员函数,GetText,和,SetText,4。,添加内部成员变量,m_pText,记录内部文本信息。,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),/初始化接口映射表,BEGIN_INTERFACE_MAP(CTextObject, CCmdTarget),INTERFACE_PART(CTextObject, IID_IPersistStream, PersistStream),INTERFACE_PART(CTextObject, IID_ITextObject, Dispatch),END_INTERFACE_MAP(),永久对象一共实现了两个接口,IDispatch,和,IPersistStream。,17,6.实现属性,GetText() SetText(),7,实现接口,IPersistStream,的成员函数(,IUnknown,的函数),AddRef Release QueryInterface,STDMETHODIMP_(ULONG) 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 = CTextObject:guid;,/,由,DECLARE_OLECREATE,定义。供类厂,COleClassFactory,使用,return NOERROR; /,是,IPersist,的函数。,STDMETHODIMP CTextObject:XPersistStream:IsDirty(),METHOD_PROLOGUE(CTextObject, PersistStream),ASSERT_VALID(pThis);,return NOERROR;,/,采取了简化处理。,18,STDMETHODIMP CTextObject:XPersistStream:Load(LPSTREAM pStm), ULONG nLength;,STATSTG statstg;,METHOD_PROLOGUE(CTextObject, PersistStream),ASSERT_VALID(pThis);/,/,得到父类指针,if(pThis-m_pText != NULL) ,delete pThis-m_pText;,/,清空原有内容,VERIFY(pStm-Stat(,/,得到流的属性,int nSize = statstg.cbSize.LowPart;,/ assume 0) ,pThis-m_pText = new charnSize;,pStm-Read(pThis-m_pText, nSize, ,/,调用流的,Read,方法从流中读取数据存到内部成员中,return NOERROR;,此函数会被用户调用,并输入流指针作为参数。,19,STDMETHODIMP 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, 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, /,创建子存储对象,ASSERT(pSubStg != NULL);,ReadDirectory(szNewPath, pSubStg);/,/,递归调用,pSubStg-Release();,.,23,.,CStdio(szNewPath, C);,if(szData, 511) /,/,读取文件,TRACE(%sn, szData);,VERIFY(pStg-CreateStream(T2COLE(szStreamName),STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,0, 0, /,创建流对象,ASSERT(pStream != NULL);,ITextObject textObject;/,/,永久对象包装类,VERIFY(textObject.CreateDispatch(g_clsid);,/,得到永久对象的自动化接口,textObject.m_lpDispatch-QueryInterface(IID_IPersistStream,(void*) ,/,从自动化接口查询永久接口,ASSERT(pPersistStream != NULL);,textObject.SetText(COleVariant(szData);,/,用包装类调用自动化接口属性,pPersistStream-Save(pStream, TRUE);,/,用永久接口向流对象中保存数据,完全可以不用这种办法,这里只是简单地走过场。,pPersistStream-Release();,pStream-Release();,.,这里展示的技术都不是必须的。可以有灵活的多样的办法。见自动化一章。,读取复合文档的例子方法同此类似,使用了存储对象的,EnumElements,函数枚举所有的子存储和子流。使用,OpenStorage OpenStream,打开存储和流。见,p236,24,
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 图纸专区 > 课件教案


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!