枚举复合文件的存储结构

Word和Excel等文件均称为复合文件。这类文件内部有一个“文件系统”,采用“磁盘文件”的组织方式来组织文件内的数据,也称为“文件中的文件系统”。

每个复合文件中有一个“根存储”(类似于文件系统中的“根目录”),根存储之下是若干“子存储”(类似于“子目录”)和“数据流”(类似于“文件”),子存储之下可以再有子存储和数据流……。

下列代码可将任一复合文件的文件结构进行枚举,如配合树型控件(如:CTreeCtrl),可将文件的存储结构清晰的展现出来。

#include  < atlconv.h >

void  DocFileViewer(LPCTSTR lpszPathName) 
{
    
//  lpszPathName: 复合文件存储路径

    
//  COM 初始化
    
//  如果是MFC程序,可以使用AfxOleInit()替代
    ::CoInitialize(NULL);

    USES_CONVERSION;

    LPCTSTR lpFileName 
=  lpszPathName;
    HRESULT hr;
    IStorage 
*  pStg  =  NULL;
    
    LPCOLESTR lpwFileName 
=  T2COLE(lpFileName);     //  转换T类型为宽字符
    hr  =  ::StgIsStorageFile(lpwFileName);         //  是复合文件吗?
     if  (FAILED(hr))
    {
        
return  FALSE;
    }
    hr 
=  ::StgOpenStorage(         //  打开复合文件
        lpwFileName,         //  文件名称
        NULL,
        STGM_READWRITE 
|  STGM_DIRECT  |  STGM_SHARE_EXCLUSIVE,
        
0 ,
        
0 ,
        
& pStg);             //  得到根存储接口指针

    EnumStorage(pStg);        
//  开始枚举

    
if  (pStg)
    {
        pStg
-> Release();
    }

    
//  COM 释放
    
//  如果使用了AfxOleInit(),则无需调用该函数
    ::CoUninitialize();
}

void  EnumStorage(IStorage  * pStg)
{
    USES_CONVERSION;

    IEnumSTATSTG 
*  pEnum  =  NULL;     //  枚举器
    HRESULT hr;

    hr 
=  pStg -> EnumElements( 0 , NULL,  0 & pEnum);
    ASSERT(SUCCEEDED(hr));

    STATSTG statstg;
    IStorage 
*  pStgSub  =  NULL;     //  子存储接口指针

    
while  (pEnum -> Next( 1 & statstg, NULL)  ==  NOERROR)
    {
        
//  statstg.type 保存着对象类型 STGTY_STREAM 或 STGTY_STORAGE
        
//  statstg.pwcsName 保存着对象名称
        
//  ...... 还有时间,长度等很多信息。请查看 MSDN

        
switch  (statstg.type)
        {
        
case  STGTY_STORAGE:     //  子存储

            
//  ...

            hr 
=  pStg -> OpenStorage(         //  打开子存储
                statstg.pwcsName,
                NULL,
                STGM_READWRITE 
|  STGM_DIRECT  |  STGM_SHARE_EXCLUSIVE,
                NULL,
                
0 ,
                
& pStgSub);         //  得到子存储接口指针

            
if  (FAILED(hr))
            {
                
return ;
            }

            EnumStorage(pStgSub);        
//  递归枚举子存储

            
break ;

        
case  STGTY_STREAM:     //  数据流

            
//  ...

            
break ;
        }

        ::CoTaskMemFree(statstg.pwcsName);    
//  释放名称所使用的内存
    }
    
    
if  (pEnum)
    {
        pEnum
-> Release();
    }

    
if  (pStgSub)
    {
        pStgSub
-> Release();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值