对复合文件的文件结构进行枚举

Word和Excel等文件均称为复合文件。这类文件内部有一个“文件系统”,采用“磁盘文件”的组织方式来组织文件内的数据,也称为“文件中的文件系统”。
    每个复合文件中有一个“根存储”(类似于文件系统中的“根目录”),根存储之下是若干“子存储”(类似于“子目录”)和“数据流”(类似于“文件”),子存储之下可以再有子存储和数据流……。
下列代码可将任一复合文件的文件结构进行枚举,如配合树型控件(如:CTreeCtrl),可将文件的存储结构清晰的展现出来。
#include <atlconv.h>

 

void DocFileViewer(LPCTSTR 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 ;
 }

 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:    // 数据流
   if(wcscmp( statstg.pwcsName,L"INFOMATION_STREAM")==0)
   {
    
   }

  // ...

  break;
 }

 ::CoTaskMemFree(statstg.pwcsName);
 }

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

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


}

 

posted @ 2009-03-09 19:53  巩固  阅读(780)  评论(0编辑  收藏  举报