枚举复合文件的存储结构

news/2024/8/26 17:03:23

枚举复合文件的存储结构     
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();
    }
}
 


http://www.niftyadmin.cn/n/1996047.html

相关文章

tapestry自定义基本IEngineService

tapestry自定义基本IEngineService tapestry的SeviceLink组件能调用9种基本的service&#xff08;ActionService, AssetService, DirectService, EngineServiceInnerProxy, EngineServiceOuterProxy, ExternalService, HomeService, Pa…

一个失败的案例

最近有一个新的项目团队在开发一个新的功能&#xff0c;并且决定尝试用Scrum&#xff0c;非常有幸被邀请加入&#xff0c;担任ScrumMaster。一开始的时候一切似乎都很顺利&#xff0c;我们召开了一次项目的启动会议&#xff0c;请负责的产品经理明确对结果的期望&#xff0c;并…

static_cast揭密

static_cast揭密 本文讨论static_cast<> 和 reinterpret_cast<>。 介绍大多程序员在学C前都学过C&#xff0c;并且习惯于C风格&#xff08;类型&#xff09;转换。当写C&#xff08;程序&#xff09;时&#xff0c;有时候我 们在使用static_cast<>和reinter…

POI操作Excel一些中文问题的解决方法

1. 设置工作表名 &#xff08;下文中提到的workbook为类org.apache.poi.hssf.usermodel.HSSFWorkbook的一个实例&#xff09; 如果使用workbook.createSheet(sheetname)或者使用workbook.setSheetName(1, "中文")&#xff0c;默认会使用ENCODING_COMPRESSED_U…

02-CSS基础与进阶-day9_2018-09-12-21-27-10

z-index 当对多个元素设置定位时,重叠的定位元素可以通过z-index调整堆叠顺序 其值可以为0 正数 负数 特点 1 z-index默认值为0 取值越大 定位元素在层叠元素上越局上 2 z-index取值一样&#xff0c;后来居上 3 z-index值不能加单位 4 只有定位元素才有该属性&#xff0c;其余如…

讨论static_cast 和 reinterpret_cast

讨论static_cast 和 reinterpret_cast 作者&#xff1a;Sam NG 译者&#xff1a;小刀人 原文链接&#xff1a;What static_cast<> is actually doing 本文讨论static_cast<> 和 reinterpret_cast<>。 介绍大 多程序员在学C前都学过C&#xff0c;并且…

awk调用date命令

创建文件date.awk&#xff1a; $8 107582685 { cmd "date %Y-%m-%d-%H -d \"" $11 "\""while (cmd | getline line) {print line}close(cmd)} 调用命令: awk -f date.awk *.log | sort | uniq -dc | sort -nr sort参数: -n // 以数值来排…

VC6调用WebService

VC6调用WebService 作者&#xff1a;未知 来源&#xff1a;月光软件站 加入时间&#xff1a;2005-2-28 月光软件站 下面是个控制台的样例Toolkit3.0 终于给出VC6的样例了&#xff0c;1.0只能看到VB和ASP的 #include <stdio.h> #import "msxml4.dll" using…