首頁 考試吧論壇 Exam8視線 考試商城 網(wǎng)絡(luò)課程 模擬考試 考友錄 實用文檔 求職招聘 論文下載
2011中考 | 2011高考 | 2012考研 | 考研培訓(xùn) | 在職研 | 自學(xué)考試 | 成人高考 | 法律碩士 | MBA考試
MPA考試 | 中科院
四六級 | 職稱英語 | 商務(wù)英語 | 公共英語 | 托福 | 雅思 | 專四專八 | 口譯筆譯 | 博思 | GRE GMAT
新概念英語 | 成人英語三級 | 申碩英語 | 攻碩英語 | 職稱日語 | 日語學(xué)習(xí) | 法語 | 德語 | 韓語
計算機等級考試 | 軟件水平考試 | 職稱計算機 | 微軟認證 | 思科認證 | Oracle認證 | Linux認證
華為認證 | Java認證
公務(wù)員 | 報關(guān)員 | 銀行從業(yè)資格 | 證券從業(yè)資格 | 期貨從業(yè)資格 | 司法考試 | 法律顧問 | 導(dǎo)游資格
報檢員 | 教師資格 | 社會工作者 | 外銷員 | 國際商務(wù)師 | 跟單員 | 單證員 | 物流師 | 價格鑒證師
人力資源 | 管理咨詢師考試 | 秘書資格 | 心理咨詢師考試 | 出版專業(yè)資格 | 廣告師職業(yè)水平
駕駛員 | 網(wǎng)絡(luò)編輯
衛(wèi)生資格 | 執(zhí)業(yè)醫(yī)師 | 執(zhí)業(yè)藥師 | 執(zhí)業(yè)護士
會計從業(yè)資格考試會計證) | 經(jīng)濟師 | 會計職稱 | 注冊會計師 | 審計師 | 注冊稅務(wù)師
注冊資產(chǎn)評估師 | 高級會計師 | ACCA | 統(tǒng)計師 | 精算師 | 理財規(guī)劃師 | 國際內(nèi)審師
一級建造師 | 二級建造師 | 造價工程師 | 造價員 | 咨詢工程師 | 監(jiān)理工程師 | 安全工程師
質(zhì)量工程師 | 物業(yè)管理師 | 招標(biāo)師 | 結(jié)構(gòu)工程師 | 建筑師 | 房地產(chǎn)估價師 | 土地估價師 | 巖土師
設(shè)備監(jiān)理師 | 房地產(chǎn)經(jīng)紀人 | 投資項目管理師 | 土地登記代理人 | 環(huán)境影響評價師 | 環(huán)保工程師
城市規(guī)劃師 | 公路監(jiān)理師 | 公路造價師 | 安全評價師 | 電氣工程師 | 注冊測繪師 | 注冊計量師
繽紛校園 | 實用文檔 | 英語學(xué)習(xí) | 作文大全 | 求職招聘 | 論文下載 | 訪談 | 游戲
您現(xiàn)在的位置: 考試吧(Exam8.com) > 計算機等級考試 > 計算機二級 > Delphi > 復(fù)習(xí)資料 > 正文

2011等考Delphi:開發(fā)Delphi對象式數(shù)據(jù)管理功能

在本章中將介紹Stream對象和Filer對象的實現(xiàn)原理、應(yīng)用方法以及在超媒體系統(tǒng)中的應(yīng)用。這對于運用Delphi 開發(fā)高級應(yīng)用是很重要的。

  13. Error方法

  聲明:function Error(const Message: String): Boolean; virtual;

  Error方法定義在Reader對象的protected部分,它是用于Reader對象的OnError事件。其返回值決定是否繼續(xù)錯誤處理過程。如果返回值為True,則表示用程序應(yīng)當(dāng)繼續(xù)錯誤處理;如果返回值為False,則表示錯誤情況被忽略。

  如果讀部件或?qū)傩猿鲥e。Reader對象調(diào)用Error方法。缺省情況下,Error將返回值設(shè)為False,然后調(diào)用OnError事件處理過程。

  TReader對象總是在try…except程序塊的except部分,并提供用戶忽略錯誤的機會。Error的使用方法如下:

  try

  … { 讀部件 }

  except

  on E: Exception do

  begin

  …{ 執(zhí)行一些清除操作 }

  if Error(E.Message) then raise;

  end;

  end;

  14. OnError事件

  聲明:property OnError: TReaderError;

  當(dāng)Reader對象讀取數(shù)據(jù)出錯時將引發(fā)OnError事件。通過處理OnError事件,可以有選擇地處理或忽略錯誤。

  傳給OnError事件處理過程的最后一個參數(shù)是名為Handled的var參數(shù)。在缺省情況下,Error方法將Handled置為True。這將阻止錯誤更進一步處理。如果事件處理過程仍舊將Handled置為False,Reader對象將引發(fā)一個EReadError異常事件。

  15. SetName方法

  聲明:procedure SetName(Component: TComponent; var Name: String virtual);

  SetName方法允許Reader對象在將從流中讀取的部件的Name值賦給部件的Name屬性前修改Name值。ReadComponent方法在讀取部件的屬性值和其它數(shù)據(jù)前先讀部件的類型和名字在讀完名字后,ReadComponent將所讀的名字作為Name參數(shù)傳給SetName,Name 是個var參數(shù),因此SetName能在返回前修改字符串值。SetName還調(diào)用了OnSetName事件處理過程,將名字字符串作為var參數(shù)傳入事件處理過程中,因此,事件處理過程也可修改字符串的值。

  16. OnSetName事件

  聲明:property OnSetName: TSetNameEvent;

  OnSetName事件發(fā)生在Read對象設(shè)置部件的Name屬性前,OnSetName事件處理過程的var參數(shù)Name參數(shù)是一個var參數(shù),因此,事件處理過程再將Name賦給部件前,可以修改Name的值。這對于想過濾窗體中部件的名字是很有幫助的。

  下面的OnSetName事件處理過程,命名了名字中包含“Button”的部件,并用“PushButton”替代。

  procedure TForm1.ReaderSetName(Reader: TReader; Component: TComponent;

  var Name: string);

  var

  ButtonPos: Integer;

  begin

  ButtonPos := Pos('Button', Name);

  if ButtonPos <> 0 then

  Name := Copy(Name, 1, ButtonPos - 1) + 'PushButton' +

  Copy(Name, ButtonPos + 6, Length(Name));

  end;

  17. ReadValue方法

  聲明:function ReadValue: TValueType;

  ReadValue方法讀取流中緊著的項目的類型,函數(shù)返回后,流的指針移到值類型指示符之后。

  TValueType是枚舉類型。存儲在Filer對象的流中的每個項目之前都有一個字節(jié)標(biāo)識該項目的類型,在讀每個項目之前都要讀取該字節(jié),以指導(dǎo)調(diào)用哪個方法來闈取項目。該字節(jié)的值就TValuetype定義的值類型之一。

  18. NextValue方法

  聲明:function Nextvalue: TValuetype;

  Nextvalue方法的作用也是返回Reader對象流中緊接著的項目的類型,它與ReadValue的區(qū)別在于并不移動指針位置。

  19. ReadBoolean方法

  聲明:function ReadBoolean: Boolean;

  ReadBoolean方法從Reader對象的流中讀取一個布爾值,并相應(yīng)地移動流位置指針。

  20、ReadChar方法

  聲明:function ReadChar: char;

  ReadChar方法從Reader對象的流中讀取一個字符。

  21. ReadFloat方法

  聲明:function ReadFloat: Extended;

  ReadFloat方法從流中讀取浮點數(shù)。

  20. ReadIdent方法

  聲明:function ReadIdent: string;

  ReadIdent方法從流中讀取標(biāo)識符。

  23. ReadInteger方法

  聲明:function ReadInteger: Longin

  ReadInteger方法從流中讀取整型數(shù)字。

  24.ReadString方法

  聲明:function Read String: string;

  ReadString方法從Reader對象的流中讀取一個字符串,并返回字符串中的內(nèi)容。該字符串是由Writer對象的WriteString方法寫入。

  20.2.3.2 TReader對象的實現(xiàn)

  Filer對象的作用主要是Delphi用來在DFM文件中讀寫各種類型的數(shù)據(jù)(包括部件對象)。這些數(shù)據(jù)的一個本質(zhì)特征是變長,而且Filer對象將讀寫數(shù)據(jù)操作抽象化,包裝成對象提供了大量的讀寫方法,方便了程序的調(diào)用。因此在應(yīng)用程序中可以廣泛使Filer對象,充分利用Delphi的面向?qū)ο蠹夹g(shù)。而且Filer對象與Stream對象捆綁在一起,一方面可以在各種存儲媒介中存取任意格式的數(shù)據(jù);另一方面,由于充分利用面向?qū)ο蟮膭討B(tài)聯(lián)編,各種讀寫方法的使用方法是一致的,因此,方法調(diào)用很簡單。下面我們著重介紹Reader 對象中與讀寫數(shù)據(jù)操作有關(guān)的屬性和方法的實現(xiàn)。

  1. TReader屬性的實現(xiàn)

  在TReader對象的屬性實現(xiàn)中我們重點介紹Position的實現(xiàn)。

  Position屬性的定義了使用了讀寫控制,它們分別是GetPosition和SetPosition方法。

  TReader = class(TFiler)

  private

  …

  function GetPosition: Longint;

  procedure SetPosition(Value: Longint);

  public

  …

  property Position: Longint read GetPosition write SetPosition;

  end;

  Postition的讀寫控制方法如下:

  function TReader.GetPosition: Longint;

  begin

  Result := FStream.Position + FBufPos;

  end;

  procedure TReader.SetPosition(Value: Longint);

  begin

  FStream.Position := Value;

  FBufPos := 0;

  FBufEnd := 0;

  end;

  在TReader的父對象TFiler對象中介紹過FBufPos和FBufEnd變量。Filer對象內(nèi)部分配了一個BufSize大小的緩沖區(qū)FBufPos就是指在緩沖區(qū)中的相對位置,F(xiàn)BufEnd是指在緩沖區(qū)中數(shù)據(jù)結(jié)束處的位置(緩沖區(qū)中的數(shù)據(jù)不一定會充滿整個緩沖區(qū))。

  在GetPosition方法中可以看到Reader對象的Position值和Stream對象的Position值是不同的。Reader對象多了一個FButPos的編移量。

  2. Defineproperty和DefineBinaryproperty方法的實現(xiàn)

  這兩個方法是虛方法,在TFiler中是抽象方法,在TReader和TWriter對象中才有具體的實現(xiàn)。

  它們在TReader中的實現(xiàn)如下:

  procedure TReader.DefineProperty(const Name: string; ReadData: TReaderProc;

  WriteData: TWriterProc; HasData: Boolean);

  begin

  if CompareText(Name, FPropName) = 0 then

  begin

  ReadData(Self);

  FPropName := '';

  end;

  end;

  procedure TReader.DefineBinaryProperty(const Name: string;

  ReadData, WriteData: TStreamProc; HasData: Boolean);

  var

  Stream: TMemoryStream;

  Count: Longint;

  begin

  if CompareText(Name, FPropName) = 0 then

  begin

  if ReadValue <> vaBinary then

  begin

  Dec(FBufPos);

  SkipValue;

  FCanHandleExcepts := True;

  PropValueError;

  end;

  Stream := TMemoryStream.Create;

  try

  Read(Count, SizeOf(Count));

  Stream.SetSize(Count);

  Read(Stream.Memory^, Count);

  FCanHandleExcepts := True;

  ReadData(Stream);

  finally

  Stream.Free;

  end;

  FPropName := '';

  end;

  end;

  在兩個方法都將Name參數(shù)值與當(dāng)前的屬性名比較,如果相同則進行讀操作。在DefineBinaryproperty中,創(chuàng)建了一個內(nèi)存流。先將數(shù)據(jù)讀到內(nèi)存流中然后調(diào)用ReadData讀取數(shù)據(jù)。

  3. FlushBuffer的實現(xiàn)

  FlushBuffer方法用于清除Reader對象的內(nèi)部緩沖區(qū)中的內(nèi)容,保持Reader對象和流在位置(Position)上的同步,其實現(xiàn)如下:

  procedure TReader.FlushBuffer;

  begin

  FStream.Position := FStream.Position - (FBufEnd - FBufPos);

  FBufPos := 0;

  FBufEnd := 0;

  end;

  4. ReadListBegin、ReadListEnd和EndOfList方法

  這三個方法都是用于從Reader對象的流中讀取一連串的項目,并且這些項目都由WriteListBegin寫入的標(biāo)志標(biāo)定開始和WriteListEnd寫入標(biāo)志,標(biāo)定結(jié)束,在讀循環(huán)中用EndOfList進行判斷。它們是在Reader對象讀取流中數(shù)據(jù)時經(jīng)常用于的。它們的實現(xiàn)如下:

  procedure TReader.ReadListBegin;

  begin

  CheckValue(vaList);

  end;

  procedure TReader.ReadListEnd;

  begin

  CheckValue(vaNull);

  end;

  function TReader.EndOfList: Boolean;

  begin

  Result := ReadValue = vaNull;

  Dec(FBufPos);

  end;

  項目表開始標(biāo)志是VaList,項目表結(jié)束標(biāo)志是VaNull,VaList和VaNull都是枚舉類型TValueType定義的常量。

  它們實現(xiàn)中調(diào)用的CheckValue是TReader的私有方法,其實現(xiàn)如下:

  procedure TReader.CheckValue(Value: TValueType);

  begin

  if ReadValue <> Value then

  begin

  Dec(FBufPos);

  SkipValue;

  PropValueError;

  end;

  end;

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

  EndOfList函數(shù)只是簡單地判斷下一字節(jié)是否是VaNull將判斷結(jié)果返回,并將字節(jié)移回原來位置。

  5. 簡單數(shù)據(jù)類型讀方法的實現(xiàn)

  簡單數(shù)據(jù)類型指的是布爾型、字符型、整型、字符串型、浮點型、集合類型和標(biāo)識符。將它們放在一起介紹是因為它們的實現(xiàn)方法類似。

  因為它們的實現(xiàn)都用到了ReadValue方法,因此先來介紹ReadValue方法的實現(xiàn):

  function TReader.ReadValue: TValueType;

  begin

  Read(Result, SizeOf(Result));

  end;

  該方法調(diào)用私有方法Read,從Reader對象流中讀一個字節(jié),并移動位置指針。

  ReadValue方法專門從流中讀取值的類型的,所有的數(shù)據(jù)讀寫方法中在讀取數(shù)據(jù)前都要調(diào)用ReadValue方法判斷是否是所要讀的數(shù)據(jù)。如果是,則調(diào)用Read方法讀取數(shù)據(jù);否則觸發(fā)一個異常事件,下面看Integer類型的讀方法:

  function TReader.ReadInteger: Longint;

  var

  S: Shortint;

  I: Smallint;

  begin

  case ReadValue of

  vaInt8:

  begin

  Read(S, SizeOf(Shortint));

  Result := S;

  end;

  vaInt16:

  begin

  Read(I, SizeOf(I));

  Result := I;

  end;

  vaInt32:

  Read(Result, SizeOf(Result));

  else

  PropValueError;

  end;

  end;

  因為Delphi 2.0中,整型可分8位、16位和32位,因此讀取整型數(shù)據(jù)時分別作了判斷。

  布爾類型的數(shù)據(jù)是直接放在值類型標(biāo)志上,如果類型為VaTrue,則值為True;如果類型為VaFalse,則值為False。

  function TReader.ReadBoolean: Boolean;

  begin

  Result := ReadValue = vaTrue;

  end;

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

  function TReader.ReadString: string;

  var

  L: Integer;

  begin

  L := 0;

  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類型緊接著一個字節(jié)存有字符串的長度;如果是VaLString類,則緊接著兩個字節(jié)存放字符串長度,然后根據(jù)字符串長度用SetString過程給分配空間,用Read方法讀出數(shù)據(jù)。

  ReadFloat方法允許將整型值轉(zhuǎn)換為浮點型。

  function TReader.ReadFloat: Extended;

  begin

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

  begin

  Dec(FBufPos);

  Result := ReadInteger;

  end;

  end;

  字符類型數(shù)據(jù)設(shè)有直接的標(biāo)志,它是根據(jù)VaString后面放一個序值為1的字節(jié)來判斷的。

  function TReader.ReadChar: Char;

  begin

  CheckValue(vaString);

  Read(Result, 1);

  if Ord(Result) <> 1 then

  begin

  Dec(FBufPos);

  ReadStr;

  PropValueError;

  end;

  Read(Result, 1);

  end;

  出于讀取DFM文件需要,F(xiàn)iler對象支持讀取標(biāo)識符。

  function TReader.ReadIdent: string;

  var

  L: Byte;

  begin

  case ReadValue of

  vaIdent:

  begin

  Read(L, SizeOf(Byte));

  SetString(Result, PChar(nil), L);

  Read(Result[1], L);

  end;

  vaFalse:

  Result := 'False';

  vaTrue:

  Result := 'True';

  vaNil:

  Result := 'nil';

  else

  PropValueError;

  end;

  end;

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

  6. 讀取部件的方法的實現(xiàn)

  Reader對象中用于讀取部件的方法有ReadSignature、ReadPrefix、ReadComponent、ReadRootComponent和ReadComponents。

  ReadSignature方法主要用于讀取Delphi Filer對象標(biāo)簽一般在讀取部件前,都要用調(diào)用ReadSignature方法以指導(dǎo)部件讀寫過程。

  procedure TReader.ReadSignature;

  var

  Signature: Longint;

  begin

  Read(Signature, SizeOf(Signature));

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

  end;

  FilerSignature就是Filer對象標(biāo)簽其值為“TPF0” ,如果讀的不是“TPF0” ,則會觸發(fā)SInValidImage異常事件。

  ReadPrefix方法是用于讀取流中部件前的標(biāo)志位,該標(biāo)志表示該部件是否處于從祖先窗體中繼承的窗體中和它在窗體中的位置是否很重要。

  procedure TReader.ReadPrefix(var Flags: TFilerFlags; var AChildPos: Integer);

  var

  Prefix: Byte;

  begin

  Flags := [];

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

  begin

  Prefix := Byte(ReadValue);

  Byte(Flags) := Prefix and $0F;

  if ffChildPos in Flags then AChildPos := ReadInteger;

  end;

  end;

  TFilerFlags的定義是這樣的:

  TFilerFlag = (ffInherited, ffChildPos);

  TFilerFlags = Set of TFilerFlag;

  充當(dāng)標(biāo)志的字節(jié)的高四位是$F,低四位是集合的值,也是標(biāo)志位的真正含義。如果ffChildPos置位,則緊接著的整型數(shù)字中放著部件在窗體中的位置序值。

  ReadComponent方法用于從Reader對象的流中讀取部件。Component 參數(shù)指定了要從流中讀取的對象。函數(shù)返回所讀的部件。

  function TReader.ReadComponent(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(Result.FComponentState, csLoading);

  if not (ffInherited in Flags) then SetCompName;

  if Result = nil then Exit;

  Include(Result.FComponentState, csReading);

  Result.ReadState(Self);

  Exclude(Result.FComponentState, csReading);

  if ffChildPos in Flags then Parent.SetChildOrder(Result, Position);

  FLoaded.Add(Result);

  except

  if ComponentCreated then Result.Free;

  raise;

  end;

  end;

  ReadCompontent方法首先調(diào)用ReadPrefix方法,讀出部件標(biāo)志位和它的創(chuàng)建次序值(Create Order)。然后用ReadStr方法分別讀出部件類名和部件名。如果Component參數(shù)為nil,則執(zhí)行兩個任務(wù):

  ● 如果ffInberited 置位則從Root 找已有部件,否則,就從系統(tǒng)的Class表中找到該部件類型的定義并創(chuàng)建

  ● 如果結(jié)果不為空,將用部件的ReadState方法讀入各種屬性值,并設(shè)置部件的Parent 屬性,并恢復(fù)它在Parent部件的創(chuàng)建次序。

上一頁  1 2 3 4 5 6 7 8 9 下一頁
  相關(guān)推薦:2010年9月計算機等級考試試題及答案解析專題
       預(yù)告:名師解析2010年9月計算機等級考試試題答案
       2010年9月計算機等級考試成績查詢時間及入口
       2010年9月計算機等考成績查詢短信免費提醒開通
文章搜索
計算機等級考試欄目導(dǎo)航
版權(quán)聲明:如果計算機等級考試網(wǎng)所轉(zhuǎn)載內(nèi)容不慎侵犯了您的權(quán)益,請與我們聯(lián)系800@exam8.com,我們將會及時處理。如轉(zhuǎn)載本計算機等級考試網(wǎng)內(nèi)容,請注明出處。