复合文件是把磁盘文件系统的管理方式移植到文件中---复合文件。
复合文档是由 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; }