亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Delphi > 正文

用Delphi編寫數據報存儲控件

2019-11-18 18:26:55
字體:
來源:轉載
供稿:網友
 

一、概述

在用Delphi編寫數據庫程序時,經常涉及到數據的導入和導出操作,如:將大型數據庫中的數據存儲為便攜文件,以便于出外閱讀;將存儲在文件中的數據信息,導入到另外的數據庫中;而且,通過將數據庫中的數據存儲為數據文件,更便于程序內部和程序間交換數據,避免通過內存交換數據的煩瑣步驟,例如在筆者編寫的通用報表程序中即以該控件作為數據信息傳遞的載體。
二、基本思路
作為數據報存儲控件,應能夠存儲和讀入數據集的基本信息(如:字段名,字段的顯示名稱,字段的數據類型,記錄數,字段數,指定記錄指定字段的當前值等),應能夠提供較好的封裝特性,以便于使用。
基于此,筆者利用Delphi5.0面向對象的特點,設計開發了數據報存儲控件。
三、實現方法
編寫如下代碼單元:
unit IbDbFile;
interface
Uses Windows, SysUtils, Classes, Forms, Db, DbTables, Dialogs;
Const
Flag = '數據報-吉星軟件工作室';
Type
TDsException = Class(Exception);
TIbStorage = class(TComponent)
PRivate
FRptTitle: string; //存儲數據報說明
FPageHead: string; //頁頭說明
FPageFoot: string; //爺腳說明
FFieldNames: TStrings; //字段名表
FStreamIndex: TStrings; //字段索引
FStream: TStream; //存儲字段內容的流
FFieldCount: Integer; //字段數
FRecordCount: Integer; //記錄數
FOpenFlag: Boolean; //流是否創建標志
protected
procedure Reset; //復位---清空流的內容
procedure SaveHead(ADataSet: TDataSet; Fp: TStream); //存儲報表頭信息
procedure LoadTableToStream(ADataSet: TDataSet); //存儲記錄數據
procedure IndexFields(ADataSet: TDataSet); //將數據集的字段名保存到列表中
procedure GetHead(Fp: TFileStream); //保存報表頭信息
procedure GetIndex(Fp: TFileStream); //建立記錄流索引
procedure GetFieldNames(Fp: TFileStream); //從流中讀入字段名表
function GetFieldName(AIndex: Integer): string; //取得字段名稱
function GetFieldDataType(AIndex: Integer): TFieldType;
function GetDisplayLabel(AIndex: Integer): string; //取得字段顯示名稱
procedure SaveFieldToStream(AStream: TStream; AField: TField); //將字段存入流中
function GetFieldValue(ARecordNo, FieldNo: Integer): string; //字段的內容
public
Constructor Create(AOwner: TComponent);
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;
//property FieldStreams[RecNo, FieldIndex: Integer]: TStream read GetFieldStream;
property RecordCount: Integer read FRecordCount write FRecordCount;
property FieldCount: Integer read FFieldCount write FFieldCount;
published
property RptTitle: string read FRptTitle write FRptTitle;
property PageHead: string read FPageHead write FPageHead;
property PageFoot: string read FPageFoot write FPageFoot;
end;

function ReadAChar(AStream: TStream): Char;
function ReadAStr(AStream: TStream): string;
function ReadBStr(AStream: TStream; Size: Integer): string;
function ReadAInteger(AStream: TStream): Integer;
procedure WriteAStr(AStream: TStream; AStr: string);
procedure WriteBStr(AStream: TStream; AStr: string);
procedure WriteAInteger(AStream: TStream; AInteger: Integer);

procedure Register;
implementation

procedure Register;
begin
RegisterComponents('Data access', [TIbStorage]);
end;

function ReadAChar(AStream: TStream): Char;
Var
AChar: Char;
begin
AStream.Read(AChar, 1);
Result := AChar;
end;

function ReadAStr(AStream: TStream): string;
var
Str: String;
C : Char;
begin
Str := '';
C := ReadAChar(AStream);
While C <> #0 do
begin
Str := Str + C;
C := ReadAChar(AStream);
end;
Result := Str;
end;

function ReadBStr(AStream: TStream; Size: Integer): string;
var
Str: String;
C : Char;
I : Integer;
begin
Str := '';
For I := 1 to Size do
begin
C := ReadAChar(AStream);
Str := Str + C;
end;
Result := Str;
end;

function ReadAInteger(AStream: TStream): Integer;
var
Str: String;
C : Char;
begin
Result := MaxInt;
Str := '';
C := ReadAChar(AStream);
While C <> #0 do
begin
Str := Str + C;
C := ReadAChar(AStream);
end;
try
Result := StrToInt(Str);
except
application.MessageBox(' 當前字符串無法轉換為整數!', '錯誤',
Mb_Ok + Mb_IconError);
end;
end;


procedure WriteAStr(AStream: TStream; AStr: string);
begin
AStream.Write(Pointer(AStr)^, Length(AStr) + 1);
end;

procedure WriteBStr(AStream: TStream; AStr: string);
begin
AStream.Write(Pointer(AStr)^, Length(AStr));
end;

procedure WriteAInteger(AStream: TStream; AInteger: Integer);
var
S : string;
begin
S := IntToStr(AInteger);
WriteAstr(AStream, S);
end;

Constructor TIbStorage.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FOpenFlag := False; //確定流是否創建的標志
end;

Destructor TIbStorage.Destroy;
begin
if FOpenFlag then
begin
FStream.Free;
FStreamIndex.Free;
FFieldNames.Free;
end;
inherited Destroy;
end;

procedure TIbStorage.Open;
begin
FOpenFlag := True;
FStream := TMemoryStream.Create;
FStreamIndex := TStringList.Create;
FFieldNames := TStringList.Create;
Reset;
end;

procedure TIbStorage.Reset; //復位
begin
if FOpenFlag then
begin
FFieldNames.Clear;
FStreamIndex.Clear;
FStream.Size := 0;
FRptTitle := '';
FPageHead := '';
FPageFoot := '';
FFieldCount := 0;
FRecordCount := 0;
end;
end;

//-------保存數據部分
procedure TIbStorage.SaveToFile(ADataSet: TDataSet; AFileName: string);
var
Fp: TFileStream;
I : Integer;
Ch: Char;
T1, T2: TDateTime;
Str: string;
begin
if Not FOpenFlag then
begin
showmessage(' 對象沒有打開');
Exit;
end;
try
if FileExists(AFileName) then DeleteFile(AFileName);
Fp := TFileStream.Create(AFileName, fmCreate);
Reset;
SaveHead(ADataSet, Fp); //保存頭部信息---附加說明
IndexFields(ADataSet); //將數據集的字段信息保存到FFieldName
LoadTableToStream(ADataSet); //保存數據集的數據信息
WriteAStr(Fp, FFieldNames.Text); //存儲字段名信息
Ch := '@';
Fp.Write(Ch, 1);
WriteAStr(Fp, FStreamIndex.Text); //存儲字段索引列表
Ch := '@';
Fp.Write(Ch, 1);
Fp.CopyFrom(FStream, 0);
finally
Fp.Free;
end;
end;

procedure TIbStorage.SaveHead(ADataSet: TDataSet; Fp: TStream);
Var
I : Integer;
Ch: Char;
begin
if Not ADataSet.Active then ADataSet.Active := True;
WriteAStr(Fp, Flag);
WriteAStr(Fp, FRptTitle);
WriteAStr(Fp, FPageHead);
WriteAStr(Fp, FPageFoot);
FFieldCount := ADataSet.Fields.Count;
FRecordCount := ADataSet.RecordCount;
WriteAStr(Fp, IntToStr(ADataSet.Fields.Count));
WriteAStr(Fp, IntToStr(ADataSet.RecordCount));
Ch := '@';
Fp.Write(Ch, 1);
end;

procedure TIbStorage.IndexFields(ADataSet: TDataSet);
var
I : Integer;
AField: TField;
begin
For I := 0 to ADataSet.Fields.Count - 1 do
begin
AField := ADataSet.Fields[I];
//不用FFieldNames.Values[AField.FieldName] := AField.DisplayLabel;是考慮效率
FFieldNames.Add(AField.FieldName + '=' + AField.DisplayLabel);
FFieldNames.Add(AField.FieldName + 'DataType=' + IntToStr(Ord(AField.DataType)));
end;
end;

procedure TIbStorage.LoadTableToStream(ADataSet: TDataSet);
var
No: Integer;
I, J, Size: Integer;
Tmp, Id, Str : string; //id=string(RecNO) + string(FieldNo)
Len: Integer;
Ch : Char;
BlobStream: TBlobStream;
begin
if Not FOpenFlag then
begin
showmessage(' 對象沒有打開');
Exit;
end;
try
ADataSet.DisableControls;
ADataSet.First;
No := 0;
FStreamIndex.Clear;
FStream.Size := 0;
While Not ADataSet.Eof do
begin
No := No + 1;
For J := 0 to ADataSet.Fields.Count - 1 do
begin
Id := Inttostr(NO) + '_' + IntToStr(J);
//建立流的位置的索引, 索引指向: Size#0Content
FStreamIndex.Add(Id + '=' + IntToStr(FStream.Position));
//存儲字段信息到流中
SaveFieldToStream(FStream, ADataSet.Fields[J]);
end;
ADataSet.Next;
end;
finally
ADataSet.EnableControls;
end;
end;

//如果一個字段的當前內容為空或者BlobSize<=0,則只寫入字段大小為0, 不寫入內容
procedure TIbStorage.SaveFieldToStream(AStream: TStream; AField: TField);
var
Size: Integer;
Ch: Char;
XF: TStream;
Str: string;
begin
if AField.IsBlob then
begin
//如何把一個TBlobField字段的內容存儲為流
Xf := TBlobStream.Create(TBlobField(AField), bmread);
try
if Xf.Size > 0 then
begin
Size := Xf.Size;
WriteAInteger(AStream, Size);
AStream.CopyFrom(Xf, Xf.Size);
end
else
WriteAInteger(AStream, 0);
finally
XF.Free;
end;
end
else
begin
Str := AField.AsString;
Size := Length(Str);
WriteAInteger(AStream, Size);
if Size <> 0 then
AStream.Write(Pointer(Str)^, Size);
//WriteAstr(AStream, Str);
end;
Ch := '@';
AStream.Write(Ch, 1);
end;

//------------Load Data
procedure TIbStorage.LoadFromFile(AFileName: string);
var
Fp: TFileStream;
Check: string;
begin
Reset;
try
if Not FileExists(AFileName) then
begin
showmessage(' 文件不存在:' + AFileName);
Exit;
end;
Fp := TFileStream.Create(AFileName, fmOpenRead);
Check := ReadAStr(Fp);
if Check <> Flag then
begin
Application.MessageBox(' 非法文件格式', '錯誤', Mb_Ok + Mb_IconError);
Exit;
end;
GetHead(Fp);
GetFieldNames(Fp);
GetIndex(Fp);
FStream.CopyFrom(Fp, Fp.Size-Fp.Position);
finally
Fp.Free;
end;
end;

procedure TIbStorage.GetHead(Fp: TFileStream);
begin
FRptTitle := ReadAStr(Fp);
FPageHead := ReadAstr(Fp);
FPageFoot := ReadAstr(Fp);
FFieldCount := ReadAInteger(Fp);
FRecordCount := ReadAInteger(Fp);
if ReadAChar(Fp) <> '@' then showmessage('GetHead File Error');
end;

procedure TIbStorage.GetFieldNames(Fp: TFileStream);
var
Ch: Char;
Str: string;
begin
Str := '';
Str := ReadAStr(Fp);
FFieldNames.CommaText := Str;
Ch := ReadAChar(Fp);
if Ch <> '@' then Showmessage('When get fieldnames Error');
end;

procedure TIbStorage.GetIndex(Fp: TFileStream);
var
Ch: Char;
Str: string;
begin
Str := '';
Str := ReadAStr(Fp);
FStreamIndex.CommaText := Str;
Ch := ReadAChar(Fp);
if Ch <> '@' then Showmessage('When Get Field Position Index Error');
end;

//---------Read Field's Value Part
function TIbStorage.GetFieldValue(ARecordNo, FieldNo: Integer): string;
var
Id, T : string;
Pos: Integer;
Len, I : Integer;
Er: Boolean;
begin
Result := '';
Er := False;
if ARecordNo > FRecordCount then
Er := true; //ARecordNo := FRecordCount;
if ARecordNo < 1 then
Er := True; // ARecordNo := 1;
if FieldNo >= FFieldCount then
Er := True; // FieldNo := FFieldCount - 1;
if FieldNo < 0 then
Er := True; //FieldNo := 0;
if Er then
begin
Showmessage('記錄號或者字段標號越界');
Exit;
end;
if FFieldCount = 0 then Exit;
Id := Inttostr(ARecordNO) + '_' + IntToStr(FieldNo);
Pos := StrToInt(FStreamIndex.Values[Id]);
FStream.Position := Pos;
//取得字段內容的長度
Len := ReadAInteger(FStream);
if Len > 0 then
Result := ReadBStr(FStream, Len);
if ReadAChar(FStream) <> '@' then
Showmessage('When Read Field, Find Save Format Error');
end;

procedure TIbStorage.FieldStream(ARecordNo, FieldNo: Integer; var AStream: TStream);
var
Id, T : string;
Pos: Integer;
Len, I : Integer;
Er: Boolean;
begin
Er := False;
if ARecordNo > FRecordCount then
Er := true; //ARecordNo := FRecordCount;
if ARecordNo < 1 then
Er := True; // ARecordNo := 1;
if FieldNo >= FFieldCount then
Er := True; // FieldNo := FFieldCount - 1;
if FieldNo < 0 then
Er := True; //FieldNo := 0;
if Er then
begin
TDsException.Create('GetFieldValue函數索引下標越界');
Exit;
end;
if FFieldCount = 0 then Exit;
Id := Inttostr(ARecordNO) + IntToStr(FieldNo);
Pos := StrToInt(FStreamIndex.Values[Id]);
FStream.Position := Pos;
Len := ReadAInteger(FStream);
AStream.CopyFrom(FStream, Len);
end;

function TIbStorage.GetFieldName(AIndex: Integer): string; //取得字段名稱
begin
//存儲的字段和數據類型各占一半
if ((AIndex < 0) or (AIndex >= FFieldNames.Count div 2)) then
Application.MessageBox(' 取字段名索引越界', '程序 錯誤',
Mb_Ok + Mb_IconError)
else
Result := FFieldNames.Names[AIndex*2];
end;

function TIbStorage.GetFieldDataType(AIndex: Integer): TFieldType; //取得字段名稱
begin
//存儲的字段和數據類型各占一半
if ((AIndex < 0) or (AIndex >= FFieldNames.Count div 2)) then
Application.MessageBox(' 取字段數據類型索引越界', '程序 錯誤',
Mb_Ok + Mb_IconError)
else
Result := TFieldType(StrToInt(FFieldNames.Values[FFieldNames.Names[AIndex*2+1]]));
end;

function TIbStorage.GetDisplayLabel(AIndex: Integer): string; //取得字段顯示名稱
begin
if ((AIndex < 0) or (AIndex >= FFieldNames.Count)) then
Application.MessageBox(' 取字段名索引越界', '程序 錯誤',
Mb_Ok + Mb_IconError)
else
Result := FFieldNames.Values[GetFieldName(AIndex)];
end;

end.
通過測試,該控件對Ttable,Tquery, TaodTable, TadoQuery, TibTable, TibQuery等常用的數據集控件等都能較好的支持,并且具有較好的效率(測試:1100條人事記錄,23個字段存儲為文件約用時2秒鐘)。

四、控件的基本使用方法
1.存儲數據集中的數據到文件
IbStorage1.Open; //創建存儲流
IbStorage1.SaveToFile(AdataSet, Afilename);
2.從文件中讀出數據信息
IbStorage1.Open;
IbStorage1.LoadFromFile(AfileName);
3.對數據報存儲控件中數據的訪問
Value := IbStorage1.Fields[ArecNo, AfieldNo]; //字符串類型
其它略。
五、結束語
通過編寫此數據報存儲控件,較好地解決了數據庫程序中數據的存儲和交換問題,為數據庫程序的開發提供了一種實用的控件。
該控件在Windows98,Delphi5開發環境下調試通過。


上一篇:真正的Delphi面向對象編程(一)

下一篇:在DELPHI中如何調用系統對話框

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
學習交流
熱門圖片

新聞熱點

疑難解答

圖片精選

網友關注

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
麻豆国产精品va在线观看不卡| 日韩欧美福利视频| 午夜精品一区二区三区在线视| 日本精品久久久久影院| 精品无码久久久久久国产| 欧美在线欧美在线| 亚洲aaaaaa| 欧美大片在线影院| 精品久久国产精品| 一区二区三欧美| 国产精品视频xxx| 欧美xxxx综合视频| 国产亚洲精品久久久久久777| 热久久这里只有| 国产va免费精品高清在线观看| 亚洲日韩欧美视频一区| 欧美日韩在线观看视频| 国产日韩欧美视频在线| 国产精品午夜一区二区欲梦| 欧美午夜影院在线视频| 成年人精品视频| 日韩激情在线视频| 亚洲黄页视频免费观看| 欧美疯狂做受xxxx高潮| 日本精品一区二区三区在线| 国产精品99久久久久久人| 久久视频在线看| 欧美日韩国产在线播放| 亚洲精品美女在线观看播放| 国产成人精品久久二区二区91| 亚洲欧美日本另类| 日韩中文在线不卡| 高潮白浆女日韩av免费看| 亚洲国产精品va在线看黑人动漫| 搡老女人一区二区三区视频tv| 欧美成人免费视频| www高清在线视频日韩欧美| 91中文字幕在线| 日韩免费电影在线观看| 九九视频直播综合网| 国产精品视频永久免费播放| 亚洲天堂免费观看| 国产精品一区二区三区毛片淫片| 91精品在线国产| 国产狼人综合免费视频| 欧美激情免费看| 国产精品色视频| 在线观看日韩www视频免费| 国产精品久久久久久久久粉嫩av| 日本欧美在线视频| 国产精品自产拍在线观| 668精品在线视频| 亚洲欧美自拍一区| 亚洲第一精品久久忘忧草社区| 久久亚洲精品视频| 亚洲女同性videos| 国产精品天天狠天天看| 日韩av免费在线看| 亲子乱一区二区三区电影| 久久精品一偷一偷国产| 亚洲国产精品专区久久| 国产日韩在线精品av| 亚洲欧洲视频在线| 一区二区成人av| 亚洲成人av资源网| 成人激情电影一区二区| 欧美激情小视频| 亚洲在线免费视频| 欧美日韩在线观看视频| 97在线视频观看| 国产精品黄色av| 国产偷亚洲偷欧美偷精品| 国产精品嫩草影院久久久| 国产精品一区二区久久| 91在线视频一区| 国产精品国产三级国产aⅴ浪潮| 国产成人精品最新| 91精品久久久久久综合乱菊| 91精品国产综合久久香蕉最新版| 欧美国产亚洲视频| 国产精品美女免费视频| 国产欧美在线播放| 国产一区二区三区在线免费观看| 欧美日韩一区二区在线| 国产午夜精品视频| 国产精品黄色影片导航在线观看| 久久五月情影视| 色偷偷av一区二区三区| 亚洲无亚洲人成网站77777| 亚洲一级一级97网| 在线观看国产精品日韩av| 久久久91精品国产一区不卡| 亚洲成色777777在线观看影院| 精品一区二区三区四区在线| 国产精品第一视频| 欧美午夜视频在线观看| 久久精品一本久久99精品| 欧美黑人巨大xxx极品| 中文字幕在线看视频国产欧美| 成人h猎奇视频网站| 九九视频直播综合网| 精品五月天久久| 668精品在线视频| 啪一啪鲁一鲁2019在线视频| 久久在线观看视频| 成人久久久久久| 自拍偷拍亚洲一区| 中文字幕欧美在线| 亚洲男人的天堂在线| 亚洲片在线观看| 日韩欧中文字幕| 久久久久久久香蕉网| 日韩免费看的电影电视剧大全| 日本中文字幕久久看| 久久九九热免费视频| 色悠悠久久88| 91精品久久久久久久久| 国产精欧美一区二区三区| 亚洲人精品午夜在线观看| 国产精品一区二区三| 亚洲精品视频免费| 欧美日韩黄色大片| 国产亚洲a∨片在线观看| 日韩综合中文字幕| 国产98色在线| 国产婷婷97碰碰久久人人蜜臀| 欧美日韩精品国产| 国产精品av在线播放| 欧美综合激情网| 色与欲影视天天看综合网| 欧美电影免费观看大全| 日韩电影免费观看在线观看| 中文字幕亚洲欧美| 原创国产精品91| 成人免费直播live| 中文字幕亚洲在线| 国产精品久久久久久久久久久久| 国产在线精品成人一区二区三区| 69影院欧美专区视频| 亚洲直播在线一区| 久久久国产一区二区| 伊人久久综合97精品| 日韩亚洲一区二区| 国产一区二区三区网站| 日韩经典中文字幕| 中文亚洲视频在线| 欧美在线视频免费播放| 日韩在线视频导航| 久久伊人色综合| 奇米成人av国产一区二区三区| 78m国产成人精品视频| 久久久999精品视频| 乱亲女秽乱长久久久| 成人免费在线视频网站| 久久久久久久久久久网站| 全球成人中文在线| 亚洲人av在线影院| 在线丨暗呦小u女国产精品| 国产日韩欧美自拍| 欧美视频免费在线观看| 国产精品久久久久影院日本| 日韩一区在线视频| 中文字幕日韩视频| 欧美日韩亚洲视频|