博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
复杂的结构化存取(一)
阅读量:6840 次
发布时间:2019-06-26

本文共 9344 字,大约阅读时间需要 31 分钟。

  hot3.png

之所以说复杂, 就是区别与以前谈到的 ; 这种复杂的结构化文件也有叫做"复合文档".
有些文档不是结构化的, 譬如记事本文件; 结构化的档可以分为以下几类:
标准结构化文档、自定义结构化文档(譬如 bmp 文件)和复合文档.
这里要谈到的结构化储存(复合文档)是由 Windows 系统通过 COM 提供的, 它能完成像 Windows 目录结构一样复杂的文件结构的存取; 提示一下 Windows 的目录结构: 一个目录下可以包含子目录和文件, 然后层层嵌套...
有时我们要存储的文件也可能会层层分支, 具体的文件内容也可能五花八门, 譬如分支当中的某个文件是张图片、是一个字符串列表、是一个记录(或叫结构)等等, 存储这样的文件内容恐怕用数据库也是无能为力的.
这种复合文件支持多线程, 不同的进程中的不同线程可以同时访问一个复合文件的不同部分.
复合文件最典型的实例就是 OLE(譬如在 Word 中可以嵌入电子表格); 这也或许是这种复合文件的来由.
或许有了这个东西, 出品属于自己的文件格式就成了轻而易举的事情了.
存取和访问复合文档主要使用定义在 Activex 单元的三个 COM 接口:
IStorage (类似于 Windows 的目录, 也就是文件夹);
IStream (类似于目录中的文件, 不过在这里都是"流", 每个流至少要占用 512 字节);
IEnumStatStg (用于列举 IStorage 的层次结构)
"接口" 又是一个复杂的概念, 暂时把它认作是一组函数的集合吧.
下面罗列出了所有相关的函数(现在还没有全部掌握, 学习过程中再慢慢注释):

IStorage 中的函数:

//创建一个子 IStorage 接口function CreateStorage(  pwcsName: POleStr;  {指定子 IStorage 接口的名称}  grfMode: Longint;   {指定访问模式}  dwStgFmt: Longint;  {保留, 须是 0}  reserved2: Longint; {保留, 须是 0}  out stg: IStorage   {返回子 IStorage 接口}): HResult; stdcall;//打开当前 IStorage 的子 IStoragefunction OpenStorage(  pwcsName: POleStr;           {指定子 IStorage 接口的名称}  const stgPriority: IStorage; {已存在的 IStorage 接口, 一般为 nil}  grfMode: Longint;            {指定访问模式}  snbExclude: TSNB;            {是个指针, 一般为 nil; 好像是指定要排除的元素}  reserved: Longint;           {保留, 须是 0}  out stg: IStorage            {返回打开的子 IStorage 接口}): HResult; stdcall;//创建一个子 IStream 接口function CreateStream(  pwcsName: POleStr;  {指定子 IStream 接口的名称}  grfMode: Longint;   {指定访问模式}  reserved1: Longint; {保留, 须是 0}  reserved2: Longint; {保留, 须是 0}  out stm: IStream    {返回子 IStream 接口}): HResult; stdcall;//打开当前 IStorage 的子 IStreamfunction OpenStream(  pwcsName: POleStr;  {指定子 IStream 接口的名称}  reserved1: Pointer; {保留, 须为 nil}  grfMode: Longint;   {指定访问模式}  reserved2: Longint; {保留, 须是 0}  out stm: IStream    {返回子 IStream 接口}): HResult; stdcall;//复制 IStorage, 该函数可以实现“整理文件,释放碎片空间”的功能function CopyTo(  ciidExclude: Longint;   {要排除的元素数, 可以是 0}  rgiidExclude: PIID;     {好像是以 PIID 的方式指定要排除的元素, 可以是 nil}  snbExclude: TSNB;       {指定要被排除的元素, 一般为 nil}  const stgDest: IStorage {目标 IStorage}): HResult; stdcall;//复制或移动 "子 IStorage" 或 "子 IStream" function MoveElementTo(  pwcsName: POleStr;       {要复制或移动的 IStorage 或 IStream 的名称}  const stgDest: IStorage; {目标 IStorage 的名称}  pwcsNewName: POleStr;    {给复制或移动后的 IStorage 或 IStream 指定新的名称}  grfFlags: Longint        {指定是复制还是移动, 可选值: STGMOVE_MOVE、STGMOVE_COPY}): HResult; stdcall;//提交更改, 确保更改后的流能反映在父级存储中function Commit(  grfCommitFlags: Longint {提交方式, 四个可选值见下面}): HResult; stdcall;//grfCommitFlags 可选值:STGC_DEFAULT                            = 0;STGC_OVERWRITE                          = 1;STGC_ONLYIFCURRENT                      = 2;STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE = 4;//放弃自从上次 Commit 调用以来对事务处理流所做的所有更改function Revert: HResult; stdcall;//获取当前 IStorage 的 IEnumStatStg 接口变量; IEnumStatStg 列举了 IStorage 的层次结构function EnumElements(  reserved1: Longint;   {保留, 须为 0}  reserved2: Pointer;   {保留, 须为 nil}  reserved3: Longint;   {保留, 须为 0}  out enm: IEnumStatStg {返回 IEnumStatStg 接口变量}): HResult; stdcall;//删除 "子 IStorage" 或 "子 IStream" function DestroyElement(  pwcsName: POleStr {指定名称}): HResult; stdcall;//重命名 "子 IStorage" 或 "子 IStream" function RenameElement(  pwcsOldName: POleStr; {原名}  pwcsNewName: POleStr  {新名}): HResult; stdcall;//设置元素的时间信息function SetElementTimes(  pwcsName: POleStr;      {元素名}  const ctime: TFileTime; {创建时间}  const atime: TFileTime; {访问时间}  const mtime: TFileTime  {修改时间}): HResult; stdcall;//在当前存储中建立一个特殊的流对象,用来保存 CLSIDfunction SetClass(  const clsid: TCLSID {}): HResult; stdcall;//设置状态位function SetStateBits(  grfStateBits: Longint; {}  grfMask: Longint       {}): HResult; stdcall;//返回一个 TStatStg 结构, 此结构包含该 IStorage 详细信息, 结构框架附下function Stat(  out statstg: TStatStg; {TStatStg 结构变量}  grfStatFlag: Longint   {选项, 此值可决定是否返回成员值, 见下}): HResult; stdcall;//TStatStg 结构:tagSTATSTG = record  pwcsName: POleStr;  dwType: Longint;  cbSize: Largeint;  mtime: TFileTime;  ctime: TFileTime;  atime: TFileTime;  grfMode: Longint;  grfLocksSupported: Longint;  clsid: TCLSID;  grfStateBits: Longint;  reserved: Longint;end;TStatStg = tagSTATSTG;//grfStatFlag 可选值:STATFLAG_DEFAULT = 0;STATFLAG_NONAME  = 1;
IStream 中的函数:

//从 IStream 中读取数据function Read(  pv: Pointer;      {接受数据的变量的指针}  cb: Longint;      {要读取的字节数}  pcbRead: PLongint {实际读出的字节数}): HResult; stdcall;//向 IStream 写入数据function Write(  pv: Pointer;         {要写入的数据的指针}  cb: Longint;         {要写入的字节数}  pcbWritten: PLongint {实际写入的字节数}): HResult; stdcall;//移动指针function Seek(  dlibMove: Largeint;          {要移动的字节数}  dwOrigin: Longint;           {指定移动的起点, 三种取值分别是: 开始、当前、结尾}  out libNewPosition: Largeint {返回新位置指针}): HResult; stdcall;//dwOrigin 可选值:STREAM_SEEK_SET = 0; {开始}STREAM_SEEK_CUR = 1; {当前}STREAM_SEEK_END = 2; {结尾}//更改流对象的大小function SetSize(  libNewSize: Largeint {指定新的大小, 以字节为单位}): HResult; stdcall;//复制部分数据到另一个 IStreamfunction CopyTo(  stm: IStream;           {目标 IStream}  cb: Largeint;           {要复制的字节数}  out cbRead: Largeint;   {从源中实际读出的字节数}  out cbWritten: Largeint {向目标实际写入的字节数}): HResult; stdcall;//提交更改, 确保更改后的流能反映在父级存储中function Commit(  grfCommitFlags: Longint {提交方式, 四个可选值见下面}): HResult; stdcall;//grfCommitFlags 可选值:STGC_DEFAULT                            = 0;STGC_OVERWRITE                          = 1;STGC_ONLYIFCURRENT                      = 2;STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE = 4;//放弃自从上次 Commit 调用以来对事务处理流所做的所有更改function Revert: HResult; stdcall;//限制对流中指定字节范围的访问function LockRegion(  libOffset: Largeint; {起始字节(从头算)}  cb: Largeint;        {范围长度, 以字节为单位}  dwLockType: Longint  {限制类型, 可选值附下面}): HResult; stdcall;//dwLockType 可选值:LOCK_WRITE     = 1;LOCK_EXCLUSIVE = 2;LOCK_ONLYONCE  = 4;//移除用 LockRegion 设定的字节范围的访问限制, 参数同 LockRegionfunction UnlockRegion(  libOffset: Largeint; {}  cb: Largeint;        {}  dwLockType: Longint  {}): HResult; stdcall;//返回一个 TStatStg 结构, 此结构包含该 IStream 详细信息, 结构框架附下function Stat(  out statstg: TStatStg; {TStatStg 结构变量}  grfStatFlag: Longint   {选项, 此值可决定是否返回成员值, 见下}): HResult; stdcall;//TStatStg 结构:tagSTATSTG = record  pwcsName: POleStr;  dwType: Longint;  cbSize: Largeint;  mtime: TFileTime;  ctime: TFileTime;  atime: TFileTime;  grfMode: Longint;  grfLocksSupported: Longint;  clsid: TCLSID;  grfStateBits: Longint;  reserved: Longint;end;TStatStg = tagSTATSTG;//grfStatFlag 可选值:STATFLAG_DEFAULT = 0;STATFLAG_NONAME  = 1;//再制一个与指定 IStream 相同的副本function Clone(  out stm: IStream {指定 IStream}): HResult; stdcall;
IEnumStatStg 中的函数:

//检索枚举序列中指定数目的项function Next(  celt: Longint;         {}  out elt;               {}  pceltFetched: PLongint {}): HResult; stdcall;//跳过枚举序列中指定数目的项function Skip(  celt: Longint {枚举中要跳过的元素数目}): HResult; stdcall;//将枚举序列重置到开始处function Reset: HResult; stdcall;//再制一个相同的 IEnumStatStg function Clone(  out enm: IEnumStatStg {}): HResult; stdcall;
相关的函数还有:

//创建一个复合文档, 并通过参数返回 IStorage 接口function StgCreateDocfile(  pwcsName: POleStr;    {指定文件名}  grfMode: Longint;     {指定访问模式}  reserved: Longint;    {保留, 须是 0}  out stgOpen: IStorage {返回 IStorage 接口}): HResult; stdcall;//打开一个复合文档, 并通过参数返回 IStorage 接口function StgOpenStorage(  pwcsName: POleStr;     {指定文件名}  stgPriority: IStorage; {已存在的 IStorage 接口, 一般为 nil}  grfMode: Longint;      {指定访问模式}  snbExclude: TSNB;      {是一个 POleStr(双字节字符串)类型的指针, 一般为 nil}  reserved: Longint;     {保留, 须是 0}  out stgOpen: IStorage  {返回 IStorage 接口}): HResult; stdcall;//判断指定文件是否是按照结构化方式存储的function StgIsStorageFile(  pwcsName: POleStr  {文件名}): HResult; stdcall;//function StgCreateDocfileOnILockBytes(  lkbyt: ILockBytes;    {}  grfMode: Longint;     {}  reserved: Longint;    {}  out stgOpen: IStorage {}): HResult; stdcall;//function StgOpenStorageOnILockBytes(  lkbyt: ILockBytes;     {}  stgPriority: IStorage; {}  grfMode: Longint;      {}  snbExclude: TSNB;      {}  reserved: Longint;     {}  out stgOpen: IStorage  {}): HResult; stdcall;//function StgIsStorageILockBytes(  lkbyt: ILockBytes {}): HResult; stdcall;//function StgSetTimes(  pszName: POleStr;       {}  const ctime: TFileTime; {}  const atime: TFileTime; {}  const mtime: TFileTime  {}): HResult; stdcall;//function StgOpenAsyncDocfileOnIFillLockBytes(  flb: IFillLockBytes;          {}  grfMode, asyncFlags: Longint; {}  var stgOpen: IStorage         {}): HResult; stdcall;//function StgGetIFillLockBytesOnILockBytes(  ilb: ILockBytes;        {}  var flb: IFillLockBytes {}): HResult; stdcall;//function StgGetIFillLockBytesOnFile(  pwcsName: POleStr;      {}  var flb: IFillLockBytes {}): HResult; stdcall;//function StgOpenLayoutDocfile(  pwcsDfName: POleStr;        {}  grfMode, reserved: Longint; {}  var stgOpen: IStorage       {}): HResult; stdcall;//读出 WriteClassStg 写入的 CLSID, 相当于简化调用 IStorage.Statfunction ReadClassStg(  stg: IStorage;    {}  out clsid: TCLSID {}): HResult; stdcall;//写 CLSID 到存储中, 同IStorage.SetClassfunction WriteClassStg(  stg: IStorage;    {}  const clsid: TIID {}): HResult; stdcall;//读出 WriteClassStm 写入的 CLSID function ReadClassStm(  stm: IStream;     {}  out clsid: TCLSID {}): HResult; stdcall;//写 CLSID 到流的开始位置function WriteClassStm(  stm: IStream;     {}  const clsid: TIID {}): HResult; stdcall;//写入用户指定的剪贴板格式和名称到存储中function WriteFmtUserTypeStg(  stg: IStorage;       {}  cf: TClipFormat;     {}  pszUserType: POleStr {}): HResult; stdcall;//读出 WriteFmtUserTypeStg 写入的信息function ReadFmtUserTypeStg(  stg: IStorage;           {}  out cf: TClipFormat;     {}  out pszUserType: POleStr {}): HResult; stdcall;

转载于:https://my.oschina.net/hermer/blog/320855

你可能感兴趣的文章
电脑环境变量里面的参数
查看>>
easyui easyui-filebox 显示中文
查看>>
FG面经Prepare: BST to Double LinkedList
查看>>
360开源的pika
查看>>
POJ 2503-Babelfish(map)
查看>>
提高sqlmap爆破效率
查看>>
HDOJ 5288 OO’s Sequence 水
查看>>
centos 扩容
查看>>
采用模拟账号读取Exchange server未读邮件的注意事项(链接邮箱问题)【转】
查看>>
38..Node.js工具模块---底层的网络通信--Net模块
查看>>
小tip: DOM appendHTML实现及insertAdjacentHTML
查看>>
图文介绍openLDAP在windows上的安装配置
查看>>
天气接口
查看>>
“C语言” 读书札记(二)之[程序和编程语言]
查看>>
C# winfrom设置循环暂停和继续 原文转自:http://blog.csdn.net/qwldcl/article/details/3970784...
查看>>
架构师给程序员的一封信
查看>>
[openstack问题]dashboard无法登陆进去的问题
查看>>
tar and war的一些命令
查看>>
http://poj.org/problem?id=2253
查看>>
【译】用Fragment解决屏幕旋转(状态发生变化)状态不能保持的问题
查看>>