程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> 復雜的結構化存取(一)

復雜的結構化存取(一)

編輯:Delphi

之所以說復雜, 就是區別與以前談到的 結構化文件存取; 這種復雜的結構化文件也有叫做"復合文檔".

  有些文檔不是結構化的, 譬如記事本文件; 結構化的檔可以分為以下幾類:

  標准結構化文檔、自定義結構化文檔(譬如 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 = 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;

//復制部分數據到另一個 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 = 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.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;




  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved