首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> Delphi

Delphi 開發數據報存儲控件:實現數據集離線存儲、交換與隨機訪問

     編輯:Delphi

項目背景

數據庫應用常需:導出數據為便攜文件離線閱讀、不同數據庫間遷移數據、報表程序間傳遞數據集。通過內存交換步驟繁瑣且不持久。本文介紹一個自定義組件 TIbStorage,將任意 TDataSet 後代(Table、Query、ADO、IBX 等)的結構與數據序列化為自定義二進制文件,支持字段元數據、記錄索引、Blob 字段、隨機訪問。

核心設計思路

  • 流式存儲:內存中用 TMemoryStream 構建數據,最後一次性寫入文件,效率高。
  • 自定義文件格式:文件頭(標識/標題/頁眉腳/字段數/記錄數) + 字段名表(名=顯示名, 名DataType=類型) + 索引表(RecNo_FieldNo=流偏移) + 數據流(每字段: 長度+內容+分隔符@)。
  • 索引隨機讀取:FStreamIndex (TStringList) 映射 RecNo_FieldNo -> Position,配合 GetFieldValue(RecNo, FieldNo) 實現 O(1) 字段讀取,無需加載全表。
  • Blob 支持:TBlobStream 讀取 Blob 內容寫入流,長度為 0 時僅寫 0 長度標記。

關鍵類結構

TIbStorage = class(TComponent)
private
  FRptTitle, FPageHead, FPageFoot: string; // 報告元數據
  FFieldNames: TStrings;   // 字段名與類型表 (Name=DisplayLabel, NameDataType=Type)
  FStreamIndex: TStrings;  // 索引表 "RecNo_FieldNo=StreamPosition"
  FStream: TStream;        // 數據內存流
  FFieldCount, FRecordCount: Integer;
  FOpenFlag: Boolean;      // 流是否已創建
protected
  // 核心內部方法:Reset, SaveHead, LoadTableToStream, IndexFields,
  // GetHead, GetIndex, GetFieldNames, SaveFieldToStream, GetFieldValue 等
public
  constructor Create(AOwner: TComponent); override;
  destructor Destroy; override;
  procedure Open;                    // 初始化內部流
  procedure SaveToFile(ADataSet: TDataSet; AFileName: string); // 存儲入口
  procedure LoadFromFile(AFileName: string);                    // 載入入口
  procedure FieldStream(ARecordNo, FieldNo: Integer; var AStream: TStream); // 導出字段流
  property FieldNames[Index: Integer]: string read GetFieldName;
  property FieldDataTypes[Index: Integer]: TFieldType read GetFieldDataType;
  property FieldDisplayLabels[Index: Integer]: string read GetDisplayLabel;
  property Fields[RecNo, FieldIndex: Integer]: string read GetFieldValue; // 默認屬性
published
  property RptTitle: string read FRptTitle write FRptTitle;
  property PageHead: string read FPageHead write FPageHead;
  property PageFoot: string read FPageFoot write FPageFoot;
end;

文件格式詳解

[文件頭]
Flag(標識串) + RptTitle + PageHead + PageFoot + FieldCount + RecordCount + '@'
[字段名表]  (逗號分隔的 Name=Value 對,含 DataType) + '@'
[索引表]    (逗號分隔的 RecNo_FieldNo=Position 對) + '@'
[數據流]    連續的字段塊: Length(Int) + Content(Bytes) + '@'  (Blob 同理)

使用示例

// 1. 存儲數據集到文件
IbStorage1.Open;
IbStorage1.RptTitle := '人事檔案導出';
IbStorage1.SaveToFile(ADOQuery1, 'C:\Data\Personnel.dat');

// 2. 從文件讀取並隨機訪問
IbStorage1.Open;
IbStorage1.LoadFromFile('C:\Data\Personnel.dat');
ShowMessage('記錄數: ' + IntToStr(IbStorage1.RecordCount));
ShowMessage('第 5 行第 3 欄: ' + IbStorage1.Fields[5, 2]); // 0-based FieldIndex

// 3. 導出 Blob 字段為流
var MS: TMemoryStream;
IbStorage1.FieldStream(10, 5, MS); // 第 10 記錄第 5 字段 (Blob)
MS.SaveToFile('C:\Temp\Photo.jpg');

性能測試數據

環境:Windows 98 / Delphi 5。1100 條記錄 × 23 字段,存儲耗時 約 2 秒。讀取與隨機訪問近乎瞬時。

兼容性說明

測試支持:TTable, TQuery, TAdoTable, TAdoQuery, TIBTable, TIBQuery 等所有 TDataSet 後代。核心依賴 Fields、RecordCount、First/Next/Eof、DisableControls/EnableControls 等標準方法。

總結

TIbStorage 以組件形式封裝了數據集的完整序列化/反序列化邏輯,解決了離線數據攜帶、跨庫遷移、報表數據傳遞等實際痛點。其索引機制賦予了隨機訪問能力,適合大數據量場景。代碼結構清晰,可擴展支持壓縮、加密、XML/JSON 導出等功能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved