熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Delphi編程 >> 正文

DELPHI基礎教程:開發Delphi對象式數據管理功能(四)[3]

2022-06-13   來源: Delphi編程 

  它們實現中調用的CheckValue是TReader的私有方法其實現如下

  procedure TReaderCheckValue(Value: TValueType)

  begin

  if ReadValue <> Value then

  begin

  Dec(FBufPos)

  SkipValue;

  PropValueError;

  end;

  end;

  

  CheckValue方法的功能是檢測緊接著要讀的值是否是Value指定的類型如果不是則跳過該項目並觸發一個SInvalidPropertyValue錯誤

  EndOfList函數只是簡單地判斷下一字節是否是VaNull將判斷結果返回並將字節移回原來位置

   簡單數據類型讀方法的實現

  簡單數據類型指的是布爾型字符型整型字符串型浮點型集合類型和標識符將它們放在一起介紹是因為它們的實現方法類似

  因為它們的實現都用到了ReadValue方法因此先來介紹ReadValue方法的實現

  function TReaderReadValue: TValueType;

  begin

  Read(Result SizeOf(Result))

  end;

  該方法調用私有方法Read從Reader對象流中讀一個字節並移動位置指針

  ReadValue方法專門從流中讀取值的類型的所有的數據讀寫方法中在讀取數據前都要調用ReadValue方法判斷是否是所要讀的數據如果是則調用Read方法讀取數據否則觸發一個異常事件下面看Integer類型的讀方法

  function TReaderReadInteger: Longint;

  var

  S: Shortint;

  I: Smallint;

  begin

  case ReadValue of

  vaInt:

  begin

  Read(S SizeOf(Shortint))

  Result := S;

  end;

  vaInt:

  begin

  Read(I SizeOf(I))

  Result := I;

  end;

  vaInt:

  Read(Result SizeOf(Result))

  else

  PropValueError;

  end;

  end;

  因為Delphi 整型可分位和因此讀取整型數據時分別作了判斷

  布爾類型的數據是直接放在值類型標志上如果類型為VaTrue則值為True;如果類型為VaFalse則值為False

  function TReaderReadBoolean: Boolean;

  begin

  Result := ReadValue = vaTrue;

  end;

  ReadString方法也利用ReadValue方法判斷是字符串還是長字符串

  function TReaderReadString: string;

  var

  L: Integer;

  begin

  L := ;

  case ReadValue of

  vaString:

  Read(L SizeOf(Byte))

  vaLString:

  Read(L SizeOf(Integer))

  else

  PropValueError;

  end;

  SetString(Result PChar(nil) L)

  Read(Pointer(Result)^ L)

  end;

  如果VaString類型緊接著一個字節存有字符串的長度如果是VaLString類則緊接著兩個字節存放字符串長度然後根據字符串長度用SetString過程給分配空間用Read方法讀出數據

  ReadFloat方法允許將整型值轉換為浮點型

  function TReaderReadFloat: Extended;

  begin

  if ReadValue = vaExtended then Read(Result SizeOf(Result)) else

  begin

  Dec(FBufPos)

  Result := ReadInteger;

  end;

  end;

  字符類型數據設有直接的標志它是根據VaString後面放一個序值為的字節來判斷的

  function TReaderReadChar: Char;

  begin

  CheckValue(vaString)

  Read(Result

  if Ord(Result) <> then

  begin

  Dec(FBufPos)

  ReadStr;

  PropValueError;

  end;

  Read(Result

  end;

  出於讀取DFM文件需要Filer對象支持讀取標識符

  function TReaderReadIdent: string;

  var

  L: Byte;

  begin

  case ReadValue of

  vaIdent:

  begin

  Read(L SizeOf(Byte))

  SetString(Result PChar(nil) L)

  Read(Result[] L)

  end;

  vaFalse:

  Result := False;

  vaTrue:

  Result := True;

  vaNil:

  Result := nil;

  else

  PropValueError;

  end;

  end;

  一般說來各種復雜的數據結構都是由這些簡單數據組成定義了這些方法等於給讀各種類型的數據提供了元操作使用很方便例如讀取字符串類型的數據時如果采用傳流方法還要判斷字符串的長度使用ReadString方法就不同了但應該特別注意的是這些類型數據的存儲格式是由Delphi設計的與簡單數據類型有明顯的不同因此存入數據時應當使用Writer對象相應的方法而且在讀數據前要用NextValue方法進行判斷否則會觸發異常事件

   讀取部件的方法的實現

  Reader對象中用於讀取部件的方法有ReadSignatureReadPrefixReadComponentReadRootComponent和ReadComponents

  ReadSignature方法主要用於讀取Delphi Filer對象標簽一般在讀取部件前都要用調用ReadSignature方法以指導部件讀寫過程

  procedure TReaderReadSignature;

  var

  Signature: Longint;

  begin

  Read(Signature SizeOf(Signature))

  if Signature <> Longint(FilerSignature) then ReadError(SInvalidImage)

  end;

  FilerSignature就是Filer對象標簽其值為TPF 如果讀的不是TPF 則會觸發SInValidImage異常事件

  ReadPrefix方法是用於讀取流中部件前的標志位該標志表示該部件是否處於從祖先窗體中繼承的窗體中和它在窗體中的位置是否很重要

  procedure TReaderReadPrefix(var Flags: TFilerFlags; var AChildPos: Integer)

  var

  Prefix: Byte;

  begin

  Flags := [];

  if Byte(NextValue) and $F = $F then

  begin

  Prefix := Byte(ReadValue)

  Byte(Flags) := Prefix and $F;

  if ffChildPos in Flags then AChildPos := ReadInteger;

  end;

  end;

  TFilerFlags的定義是這樣的

  TFilerFlag = (ffInherited ffChildPos)

  TFilerFlags = Set of TFilerFlag;

  充當標志的字節的高四位是$F低四位是集合的值也是標志位的真正含義如果ffChildPos置位則緊接著的整型數字中放著部件在窗體中的位置序值

  ReadComponent方法用於從Reader對象的流中讀取部件Component 參數指定了要從流中讀取的對象函數返回所讀的部件

  function TReaderReadComponent(Component: TComponent) TComponent;

  var

  CompClass CompName: string;

  Flags: TFilerFlags;

  Position: Integer;

  …

  begin

  ReadPrefix(Flags Position)

  CompClass := ReadStr;

  CompName := ReadStr;

  Result := Component;

  if Result = nil then

  if ffInherited in Flags then

  FindExistingComponent else

  CreateComponent;

  if Result <> nil then

  try

  Include(ResultFComponentState csLoading)

  if not (ffInherited in Flags) then SetCompName;

  if Result = nil then Exit;

  Include(ResultFComponentState csReading)

  ResultReadState(Self)

  Exclude(ResultFComponentState csReading)

  if ffChildPos in Flags then ParentSetChildOrder(Result Position)

  FLoadedAdd(Result)

  except

  if ComponentCreated then ResultFree;

  raise;

  end;

  end;

  ReadCompontent方法首先調用ReadPrefix方法讀出部件標志位和它的創建次序值(Create Order)然後用ReadStr方法分別讀出部件類名和部件名如果Component參數為nil則執行兩個任務

  ● 如果ffInberited 置位則從Root 找已有部件否則就從系統的Class表中找到該部件類型的定義並創建

  ● 如果結果不為空將用部件的ReadState方法讀入各種屬性值並設置部件的Parent 屬性並恢復它在Parent部件的創建次序

[]  []  []  []  


From:http://tw.wingwit.com/Article/program/Delphi/201311/25094.html
    推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.