为什么80%的码农都做不了架构师?>>>   

之所以说复杂, 就是区别与以前谈到的 结构化文件存取; 这种复杂的结构化文件也有叫做"复合文档".

有些文档不是结构化的, 譬如记事本文件; 结构化的档可以分为以下几类:
标准结构化文档、自定义结构化文档(譬如 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 的子 IStorage
function 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 的子 IStream
function 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;//在当前存储中建立一个特殊的流对象,用来保存 CLSID
function 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 = recordpwcsName: 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;//复制部分数据到另一个 IStream
function 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 设定的字节范围的访问限制, 参数同 LockRegion
function UnlockRegion(libOffset: Largeint; {}cb: Largeint;        {}dwLockType: Longint  {}
): HResult; stdcall;//返回一个 TStatStg 结构, 此结构包含该 IStream 详细信息, 结构框架附下
function Stat(out statstg: TStatStg; {TStatStg 结构变量}grfStatFlag: Longint   {选项, 此值可决定是否返回成员值, 见下}
): HResult; stdcall;//TStatStg 结构:
tagSTATSTG = recordpwcsName: 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.Stat
function ReadClassStg(stg: IStorage;    {}out clsid: TCLSID {}
): HResult; stdcall;//写 CLSID 到存储中, 同IStorage.SetClass
function 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

复杂的结构化存取(一)相关推荐

  1. 模拟便于直接存取的索引文件结构_07016.2.0使用Solr7对结构化csv文件建立全文索引...

    作者:余枫 文档编写目的 在上一篇<6.2.0-使用Solr7对多种格式文件建立全文索引>中介绍了如何在CDH6.2.0中使用Solr7对多种格式的文件进行全文索引,测试中使用的主要是非结 ...

  2. NoSQL生态系统——类似Bigtable列存储,或者Dynamo的key存储(kv存储如BDB,结构化存储如redis,文档存储如mongoDB)...

    摘自:http://www.ituring.com.cn/article/4002# NoSQL系统的数据操作接口应该是非SQL类型的.但在NoSQL社区,NoSQL被赋予了更具有包容性的含义,其意为 ...

  3. 结构化查询语言(Structured Query Language)

    2019独角兽企业重金招聘Python工程师标准>>> 结构化查询语言(Structured Query Language)简称SQL(发音:/ˈɛs kjuː ˈɛl/ " ...

  4. 软件设计的第一性原理:结构化抽象

    软件设计的第一性原理,是结构化抽象.术生于道,技术生于原理. 引语 所谓的第一性原理,就是无论使用什么方法论,都无法绕过的那最最基础的部分.无论是 DDD 设计,还是面向模式的架构设计,或 微服务架构 ...

  5. 非结构化WEB数据库与图书馆多媒体信息资源的组织利用

    1 非结构化WEB数据库简介 非结构化WEB数据库,是指其字段长度可变,并且每个字段的记录又可以由可重复或不可重复的子字段构成的基于INTERNET.INTRANET的数据库,用它不仅可以处理结构化数 ...

  6. Oracle结构化查询语言(Structured Query Language)

    SQL是结构化查询语言(Structured Query Language) 专门用于数据存取.数据更新及数据库管理等操作. 此文后积累学习用SQL语句对数据库的表进行增删改查的操作. 在Oracle ...

  7. 结构化英语查询语言SQL

    SQL(结构化英语查询语言) structured English Query Language SQL特点 集数据定义语言(DDL),数据操纵语言(DML),数据控制语言(DCL)功能于一体. 可以 ...

  8. 非结构化数据的相关知识

    一.出现原因 信息社会化时代,各行各业在处理相关业务的过程中,都累计了海量的数据信息,随着IT应用的普及和发展,传统的纸质资料存储方式在不断缩减,更多的采用电子信息的存储方式存放在计算机中.这些信息数 ...

  9. 结构化 VS 非结构化

    如果说结构化信息更多的忠实.详实地记录了企业的生产交易活动,是显性的表示,那么 非结构化信息则隐性包含了掌握着企业命脉的关键,隐含着许多提高企业效益的机会. 非结构化数据 非结构化数据库是指其字段长度 ...

最新文章

  1. Settings.System暂存/读取数据
  2. docker centos7 chrome 安装并且支持局域网远程调试
  3. Working copy XXX locked and cleanup failed in SVN
  4. python怎么改界面颜色_Python的matplotlib绘图如何修改背景颜色的实现
  5. 测试点2详解:1045 快速排序 (25分)——23行代码满分
  6. C/C++中rand()函数产生随机数的用法
  7. Angularjs切换网站配色模式简单示例1(切换css文件)
  8. Java IO(File类)
  9. 达摩院 2020 预测:感知智能的“天花板”和认知智能的“野望”
  10. int 转 const char*
  11. C# 线程间互相通信
  12. 离散数学及其应用 第一章:集合论
  13. 大学英语综合教程四 Unit 1至Unit 8 课文内容英译中 中英翻译
  14. 最新版QQ机器人搭建保姆教程,保熟【最新beta2版本】
  15. wap建站程序源码_织梦程序搭建网站实例教程,想尝试搭建网站的朋友赶紧保存了...
  16. ms office excel2013教程 - 从网站加载数据
  17. php程序员 一万小时定律,科学网—一万小时定律——阅读笔记 - 贾琳的博文
  18. WebView深究之Android是如何实现webview初始化的
  19. PAT (Basic Level) Practice (中文)题目集合
  20. linux搜狗输入法不显示候选框问题

热门文章

  1. 重新格式化NameNode后,DataNode启动不起来问题解决
  2. IOS-开发日志-UILabel相关
  3. 关于图像特征的提取【转】
  4. ubuntu上建立mini2440 qt编译环境
  5. 操作系统编写之引导扇区
  6. 公交车下发现一具男尸
  7. 支付宝支付 第七集:产品数据接口的定义和测试
  8. opencv_imread出错(release/debug、X86/X64)
  9. java的hashmap排序_Java面试题:如何对HashMap按键值排序
  10. springmvc的工作原理_SpringMVC工作原理