复合文档(Compound Document)读写栗子

时间:2021-04-24 05:45:32

  复合文件是把磁盘文件系统的管理方式移植到文件中---复合文件。   

  复合文档是由 Windows 系统通过 COM 提供的, 它能完成像 Windows 目录结构一样复杂的文件结构的存取;提示一下 Windows 的目录结构: 一个目录下可以包含子目录和文件, 然后层层嵌套...

  有时我们要存储的文件也可能会层层分支, 具体的文件内容也可能五花八门, 譬如分支当中的某个文件是张图片、是一个字符串列表、是一个记录(或叫结构)等等, 存储这样的文件内容恐怕用数据库也是无能为力的。

  或许有了这个东西, 出品属于自己的文件格式就成了轻而易举的事情了。

  存取和访问复合文档主要使用定义在 Activex 的三个 COM 接口:

  IStorage (类似于 Windows 的目录, 也就是文件夹);

  IStream (类似于目录中的文件, 不过在这里都是"流", 每个流至少要占用 512 字节);

  IEnumStatStg (用于列举 IStorage 的层次结构)

#include <iostream>
#include <Windows.h>
#include <assert.h>
#include <tchar.h>
using namespace std;

int main()
{
    ::CoInitialize(NULL);    //COM初始化   
    HRESULT hr;                //函数指向返回值  
    IStorage *pStg = NULL;  //根存储接口指针  
    IStorage *pSub = NULL;    //子存储接口指针  
    IStream *pStm = NULL;    //流接口指针   
    
    //创建复合文件  
    hr = ::StgCreateDocfile(_T("C:\\a.stg"), STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, &pStg);
    assert(SUCCEEDED(hr));

    //建立子存储  
    hr = pStg->CreateStorage(_T("SubStg"), STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &pSub);
    assert(SUCCEEDED(hr));   
    
    //建立流  
    hr = pSub->CreateStream(_T("stm"), STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &pStm);
    assert(SUCCEEDED(hr));   
    
    //向流中写入数据  
    hr = pStm->Write(_T("Hello IStorage"), 256, NULL);  
    assert(SUCCEEDED(hr));   
    
    //释放指针  
    if(pStm) pStm->Release();  
    if(pSub) pSub->Release();  
    if(pStg) pStg->Release();  
    
    //指针重新初始化
    pStg = NULL; 
    pSub = NULL;    
    pStm = NULL;     

    //打开复合文档
    hr = ::StgOpenStorage(_T("C:\\a.stg"), NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, NULL, 0, &pStg);
    assert(SUCCEEDED(hr));   

    //打开一个目录
    hr = pStg->OpenStorage(_T("SubStg"), NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, NULL, 0, &pSub); 
    assert(SUCCEEDED(hr));   

    //准备读取数据
    hr = pSub->OpenStream(_T("stm"), NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &pStm);  
    assert(SUCCEEDED(hr));   

    //读取数据
    TCHAR strText[1024] = {0};            //必须指定初始值,否则会显示出乱码,也可以设为 '/0'  
    ULONG actRead = 0;  
    hr = pStm->Read(strText,        //存放放入的数据的缓冲区  
                    1024,            //要读入数据的长度,如不清楚可以设为较大的数  
                    &actRead        //实际读入的长度  
                    );  

    //显示读取结果
    cout << "读取的数据结果为:";
    wcout << strText << endl;
    cout << "指定读入数据的长度:" << 1024 << endl;
    cout << "实际读入的数据长度:" << actRead << endl;
    
    ::CoUninitialize();        //释放COM  

    cin.get();
    return 0;
}

 复合文档(Compound Document)读写栗子