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

Delphi 第 20 章:開發物件導向資料管理功能(一)─ TStream 核心實作與元件串流化

     編輯:Delphi

20.1.1.2 TStream 實作原理核心解析

TStream 是所有串流物件的基底抽象類別。後繼串流類別主要在 Read/Write 上改進以適應不同儲存媒介。掌握 TStream 是掌握串流物件管理的關鍵。Borland 雖提供介面文件,但未公開實作細節,筆者從 Delphi 2.0 Client/Server Suite 原始碼與範例程式中習得串流技術。

1. TStream 屬性實作

TStream 定義 Position 與 Size 兩個屬性,抽象化各種儲存媒介中頻繁存取的位置與大小資訊。屬性定義採讀寫控制:

property Position: Longint read GetPosition write SetPosition;
property Size: Longint read GetSize;

Position 可讀寫,Size 唯讀。

Position 實作

function TStream.GetPosition: Longint;
begin
  Result := Seek(0, 1); { soFromCurrent }
end;

procedure TStream.SetPosition(Pos: Longint);
begin
  Seek(Pos, 0); { soFromBeginning }
end;

讀取位置呼叫 Seek(0,1) 取得目前指標;設定位置呼叫 Seek(Pos,0) 移至絕對位移。

Size 實作

function TStream.GetSize: Longint;
var
  Pos: Longint;
begin
  Pos := Seek(0, 1);       { 記住目前位置 }
  Result := Seek(0, 2);    { 移至末尾取得大小 }
  Seek(Pos, 0);            { 還原位置 }
end;

透過暫時移動指標至末尾取得大小,再還原位置。

2. TStream 方法實作

⑴ CopyFrom 方法:跨媒介資料複製

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;
    Count := Source.Size;
  end;
  Result := Count;
  GetMem(Buffer, MaxBufSize);
  try
    while Count > 0 do
    begin
      if Count > MaxBufSize then BufSize := MaxBufSize else BufSize := Count;
      N := Source.Read(Buffer^, BufSize);
      if N = 0 then Break;
      Write(Buffer^, N);
      Dec(Count, N);
    end;
  finally
    FreeMem(Buffer, MaxBufSize);
  end;
end;

CopyFrom 簡化記憶體配置、檔案開啟/讀寫細節,統一在串流物件上複製資料。參數 Source 來源串流,Count 複製位元組數(0 表全部),回傳實際複製位元組數。

⑵ ReadComponent/ReadComponentRes:元件反序列化

function TStream.ReadComponent(Instance: TComponent): TComponent;
var
  Reader: TReader;
begin
  Reader := TReader.Create(Self, 4096);
  try
    if Instance = nil then
      Result := Reader.ReadRootComponent(nil)
    else
    begin
      Reader.ReadRootComponent(Instance);
      Result := Instance;
    end;
  finally
    Reader.Free;
  end;
end;

建立 TReader 呼叫 ReadRootComponent。若 Instance=nil 依串流中類型資訊建立新元件。

ReadResHeader 讀取 Windows 資源檔頭,驗證有效性:

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 先呼叫 ReadResHeader 再呼叫 ReadComponent,用於從資源檔讀取元件。

⑶ WriteComponent/WriteDescendant:元件序列化

procedure TStream.WriteComponent(Instance: TComponent);
begin
  WriteDescendant(Instance, nil);
end;

procedure TStream.WriteDescendant(Instance, Ancestor: TComponent);
var
  Writer: TWriter;
begin
  Writer := TWriter.Create(Self, 4096);
  try
    Writer.WriteDescendant(Instance, Ancestor);
  finally
    Writer.Free;
  end;
end;

建立 TWriter 呼叫 WriteDescendant。WriteComponent 直接呼叫 WriteDescendant(Instance, nil)。

⑷ WriteComponentRes/WriteDescendantRes:資源檔寫入

procedure TStream.WriteComponentRes(const ResName: string; Instance: TComponent);
begin
  WriteDescendantRes(ResName, Instance, nil);
end;

procedure TStream.WriteDescendantRes(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;
  WriteDescendant(Instance, Ancestor);
  ImageSize := Position - Origin;
  Position := Origin - 4;
  WriteBuffer(ImageSize, SizeOf(Longint));
  Position := Origin + ImageSize;
end;

寫入標準 Windows 資源檔頭(含資源名、類型標識),再寫入元件資料,最後回填資料大小。WriteComponentRes 與 ReadComponentRes 配合可讀寫 Delphi DFM 檔案,善用 Delphi 系統功能。

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