程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> 第二十章-開發Delphi對象式數據管理功能(一)-(2)

第二十章-開發Delphi對象式數據管理功能(一)-(2)

編輯:Delphi

20.1.1.2 TStream的實現原理

TStream對象是Stream對象的基礎類,這是Stream對象的基礎。為了能在不同媒介上的存儲數據對象,後繼的Stream對象主要是在Read和Write方法上做了改進,。因此,了解TStream是掌握Stream對象管理的核心。Borland公司雖然提供了Stream對象的接口說明文檔,但對於其實現和應用方法卻沒有提及,筆者是從Borland Delphi 2.0 Client/Server Suite 提供的源代碼和部分例子程序中掌握了流式對象技術。

下面就從TStream的屬性和方法的實現開始。

1. TStream屬性的實現

前面介紹過,TStream具有Position和Size兩個屬性,作為抽象數據類型,它抽象了在各種存儲媒介中讀寫數據所需要經常訪問的域。那麼它們是怎樣實現的呢?

在自定義部件編寫這一章中介紹過部件屬性定義中的讀寫控制。Position和Size也作了讀寫控制。定義如下:

property Position: Longint read GetPosition write SetPosition;

property Size: Longint read GetSize;

由上可知,Position是可讀寫屬性,而Size是只讀的。

Position屬性的實現就體現在GetPosition和SetPosition。當在程序運行過程中,任何讀取Position的值和給Position賦值的操作都會自動觸發私有方法GetPosition和SetPosition。兩個方法的聲明如下:

function TStream.GetPosition: Longint;

begin

Result := Seek(0, 1);

end;

procedure TStream.SetPosition(Pos: Longint);

begin

Seek(Pos, 0);

end;

在設置位置時,Delphi編譯機制會自動將Position傳為Pos。

前面介紹過Seek的使用方法,第一參數是移動偏移量,第二個參數是移動的起點,返回值是移動後的指針位置。

Size屬性的實現只有讀控制,完全屏蔽了寫操作。讀控制方法GetSize實現如下:

function TStream.GetSize: Longint;

var

Pos: Longint;

begin

Pos := Seek(0, 1);

Result := Seek(0, 2);

Seek(Pos, 0);

end;

2. TStream方法的實現

⑴ CopyFrom方法

CopyFrom是Stream對象中很有用的方法,它用於在不同存儲媒介中拷貝數據。例如,內存與外部文件之間、內存與數據庫字段之間等。它簡化了許多內存分配、文件打開和讀寫等的細節,將所有拷貝操作都統一到Stream對象上。

前面曾介紹:CopyFrom方法帶Source和Count兩個參數並返回長整型。該方法將Count個字節的內容從Source拷貝到當前流中,如果Count值為0則拷貝所有數據。

function TStream.CopyFrom(Source: TStream; Count: Longint): Longint;

const

MaxBufSize = $F000;

var

BufSize, N: Integer;

Buffer: PChar;

begin

if Count = 0 then

begin

Source.Position := 0;

CouNG="ZH-CN">資源文件中的部件時調用,通常程序員不需自己調用。如果讀取的不是資源文件ReadResHeader,將觸發異常事件。

procedure TStream.ReadResHeader;

var

ReadCount: Longint;

Header: array[0..79] of Char;

begin

FillChar(Header, SizeOf(Header), 0);

ReadCount := Read(Header, SizeOf(Header) - 1);

if (Byte((@Header[0])^) = $FF) and (Word((@Header[1])^) = 10) then

Seek(StrLen(Header + 3) + 10 - ReadCount, 1)

else

raise EInvalidImage.CreateRes(SInvalidImage);

end;

ReadComponentRes在Windows資源文件中讀取部件,為了判斷是否是資源文件,它首先調用ReadResHeader方法,然後調用ReadComponent方法讀取Instance指定的部件。下面是它的實現:

function TStream.ReadComponentRes(Instance: TComponent): TComponent;

begin

ReadResHeader;

Result := ReadComponent(Instance);

end;

與ReadComponentRes相應的寫方法是WriteComponentRes,Delphi 調用這兩個方法讀寫窗體文件(DFM文件),在後面書中會舉用這兩個方法讀取DFM文件的例子。

⑷ WriteComponent和WriteDescendant方法

Stream對象的WriteDescendant方法在實現過程中,創建了TWriter對象,然後利用TWriter的WriteDescendant方法將Instance寫入流。而WriteComponent方法只是簡單地調用WriteDescendant方法將Instance寫入流。它們的實現如下:

procedure TStream.WriteComponent(Instance: TComponent);

begin

WriteDescendent(Instance, nil);

end;

procedure TStream.WriteDescendent(Instance, Ancestor: TComponent);

var

Writer: TWriter;

begin

Writer := TWriter.Create(Self, 4096);

try

Writer.WriteDescendent(Instance, Ancestor);

finally

Writer.Free;

end;

end;

⑸ WriteDescendantRes和WriteComponentRes方法

WriteDescendantRes方法用於將部件寫入Windows資源文件;而WriteComponentRes 方法只是簡單地調用WriteDescendantRes方法,它們的實現如下:

procedure TStream.WriteComponentRes(const ResName: string; Instance:

TComponent);

begin

WriteDescendentRes(ResName, Instance, nil);

end;

procedure TStream.WriteDescendentRes(const ResName: string; Instance,

Ancestor: TComponent);

var

HeaderSize: Integer;

Origin, ImageSize: Longint;

Header: array[0..79] of Char;

begin

Byte((@Header[0])^) := $FF;

Word((@Header[1])^) := 10;

HeaderSize := StrLen(StrUpper(StrPLCopy(@Header[3], ResName, 63))) + 10;

Word((@Header[HeaderSize - 6])^) := $1030;

Longint((@Header[HeaderSize - 4])^) := 0;

WriteBuffer(Header, HeaderSize);

Origin := Position;

WriteDescendent(Instance, Ancestor);

ImageSize := Position - Origin;

Position := Origin - 4;

WriteBuffer(ImageSize, SizeOf(Longint));

Position := Origin + ImageSize;

end;

WriteCompnentRes是與ReadComponentRes相應的對象寫方法,這兩個方法相互配合可讀取Delphi的DFM文件,從而利用Delphi系統的功能。

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