黄色在线观看视频-黄色在线免费看-黄色在线视频免费-黄色在线视频免费看-免费啪啪网-免费啪啪网站

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

2011等考Delphi:開發Delphi對象式數據管理功能

來源:考試吧Exam8.com) 2010-10-30 9:21:41 考試吧:中國教育培訓第一門戶 模擬考場
在本章中將介紹Stream對象和Filer對象的實現原理、應用方法以及在超媒體系統中的應用。這對于運用Delphi 開發高級應用是很重要的。

  2. TMemoryStream對象方法的實現

  ⑴ Realloc方法

  Realloc方法是TMemoryStream動態內存分配的核心,它的SetSize、SetCapacity等方法最終都是調用Realloc進行內存的分配和初始化工作的。它的實現如下:

  const

  MemoryDelta = $2000;

  function TMemoryStream.Realloc(var NewCapacity: Longint): Pointer;

  begin

  if NewCapacity > 0 then

  NewCapacity := (NewCapacity + (MemoryDelta - 1)) and not (MemoryDelta - 1);

  Result := Memory;

  if NewCapacity <> FCapacity then

  begin

  if NewCapacity = 0 then

  begin

  GlobalFreePtr(Memory);

  Result := nil;

  end else

  begin

  if Capacity = 0 then

  Result := GlobalAllocPtr(HeapAllocFlags, NewCapacity)

  else

  Result := GlobalReallocPtr(Memory, NewCapacity, HeapAllocFlags);

  if Result = nil then raise EStreamError.CreateRes(SMemoryStreamError);

  end;

  end;

  end;

  Realloc方法是以8K為單位分配動態內存的,方法中的第一句if語句就是執行該操作。如果傳入的NewCapacity參數值為0,則釋放流中的內存。Realloc方法用GLobal FreePtr函數釋放內存,用GlobalAllocPtr分配內存,用GlobalReallocPtr進行內存的重分配。如果原來的Capacity屬性值為0,則調用Globa|AllocPtr否則調用GlobalReallocPtr。最后如果Result為nil則觸發內存流錯的異常事件,否則返回指向分配的內存的指針。

  ⑵ Write方法

  Write方法從內存流內部緩沖池的當前位置開始寫入二進制數據。其實現如下:

  function TMemoryStream.Write(const Buffer; Count: Longint): Longint;

  var

  Pos: Longint;

  begin

  if (FPosition >= 0) and (Count >= 0) then

  begin

  Pos := FPosition + Count;

  if Pos > 0 then

  begin

  if Pos > FSize then

  begin

  if Pos > FCapacity then

  SetCapacity(Pos);

  FSize := Pos;

  end;

  System.Move(Buffer, Pointer(Longint(FMemory) + FPosition)^, Count);

  FPosition := Pos;

  Result := Count;

  Exit;

  end;

  end;

  Result := 0;

  end;

  Buffer中存儲要寫入流的二進制數據,如果要寫入的數據的字節超出了流的內存池的大小,則調用SetCapacity方法再分配內存,然后用內存復制函數將Buffer中的數據復制到FMemory中。接著移動位置指針,并返回寫入數據的字節數。分析這段程序可以知道,FCapacity的值和FSize的值是不同的。

  ⑶ Clear方法

  Clear方法消除內存流中的數據,將Memory屬性置為nil,并將FSize和FPosition 的值設為0。其實現如下:

  procedure TMemoryStream.Clear;

  begin

  SetCapacity(0);

  FSize := 0;

  FPosition := 0;

  end;

  ⑷ LoadFromStream和LoadFromFile方法

  LoadFromStream方法首先根據傳入的Stream的Size屬性值重新分配動態內存,然后調用Stream的ReadBuffer方法往FMemory中復制數據,結果Stream的全部內容在內存中有了一份完整拷貝。其實現如下:

  procedure TMemoryStream.LoadFromStream(Stream: TStream);

  var

  Count: Longint;

  begin

  Stream.Position := 0;

  Count := Stream.Size;

  SetSize(Count);

  if Count <> 0 then Stream.ReadBuffer(FMemory^, Count);

  end;

  LoadFromFile與LoadFromStream是一對方法。LoadFromFile首先創建了一個TFileStream對象,然后調用LoadFromStream方法,將FileStream文件流中的數據寫入MemoryStream中。

  20.1.6 TResourceStream對象

  TResourceStream對象是另一類MemoryStream對象,它提供對Windows 應用程序資源的訪問,因此稱它為資源流。TResourceSream也是從TCustomMemoryStream 繼承的。因此在TCustomMemoryStream對象的基礎上,定義了與指定資源模塊或資源文件建立連接的構造方法,并且還覆蓋了Write,以實現向資源文件中寫數據。

  下面介紹TResourceStream的實現

  1. 私有域

  TResourceStream沒有定義新的屬性,但它在private部分定義了兩個數據域HResInfo和HGlobol和一個私有方法Initialize,它們的定義如下:

  TResourceStream = class(TCustomMemoryStream)

  private

  HResInfo: HRSRC;

  HGlobal: THandle;

  procedure Initialize(Instance: THandle; Name, ResType: PChar);

  …

  end;

  HRSRC是描述Windows資源信息的結構句柄。HGlobal變量代表資源所在模塊的句柄。如果操作的是應用程序資源,HGlohal就代表EXE程序的句柄;如果是動態鏈接庫(DLL),則HGlobal 代表動態鏈接庫的句柄。TResourceStream對象使用這兩上變量訪問應用程序或動態鏈接庫中的資源。

  Initialize方法是TResourceStream對象內部使用的。它的構造方法Create和CreateFromID都是調用Initialize方法完成對TResourceStream的初始化。它的實現如下:

  procedure TResourceStream.Initialize(Instance: THandle; Name, ResType: PChar);

  procedure Error;

  begin

  raise EResNotFound.Create(FmtLoadStr(SResNotFound, [Name]));

  end;

  begin

  HResInfo := FindResource(Instance, Name, ResType);

  if HResInfo = 0 then Error;

  HGlobal := LoadResource(Instance, HResInfo);

  if HGlobal = 0 then Error;

  SetPointer(LockResource(HGlobal), SizeOfResource(Instance, HResInfo));

  end;

  該方法實現中,首先調用Windows函數FoundResource得到由參數Instance指定的模塊中的名為Name和類型為ResType的資源,然后調用LoadResource將資源調用內存,并返回該資源在內存中的句柄,最后,將該資源復制到ResourceStream中。方法的Instance參數代表要調用的資源所在的模塊句柄。模塊可以是可執行文件,也可以是動態鏈接庫。如果在讀取資源時沒在模塊中發現要找的資源則產生異常事件。

  2. 構造方法Create和CreateFromID

  這兩個方法在實現上沒有大的不同。顧名思義,第一個方法是通過資源名構造TResourceStream; 第二個方法通過資源ID構造TResourceStream,而且在實現過程中,它們都調用了Initialize方法。下面是它們的實現:

  constructor TResourceStream.Create(Instance: THandle; const ResName: string;

  ResType: PChar);

  begin

  inherited Create;

  Initialize(Instance, PChar(ResName), ResType);

  end;

  constructor TResourceStream.CreateFromID(Instance: THandle; ResID: Integer;

  ResType: PChar);

  begin

  inherited Create;

  Initialize(Instance, PChar(ResID), ResType);

  end;

  這兩個方法中都有Instance參數,該參數值的含義在Insitialize中介紹過。

  3. Write方法

  TResourceStream的Write方法只完成一件事,就產生這個異常事件,其實現如下:

  function TResourceStream.Write(const Buffer; Count: Longint): Longint;

  begin

  raise EStreamError.CreateRes(SCantWriteResourceStreamError);

  end;

  從方法實現中可以看到,TSourceStream對象是不允許寫數據的。一旦往資源流中寫數據將產生異常事件。

  4. 析構方法Destroy

  該方法產生給資源解鎖,然后釋放該資源,最后調用繼承的Destroy方法釋放ResourceStream。其實現如下:

  destructor TResourceStream.Destroy;

  begin

  UnlockResource(HGlobal);

  FreeResource(HResInfo);

  inherited Destroy;

  end;

  回顧Initialize方法,我們不難發現:

  ● ResourceStream沒有額外地給資源重新分配內存,而是直接使用HGlobal句柄所指 的內存域

  ● ResourceStream中的資源在流的生存期,始終是Lock狀態,因此要根據Windows 的內存使用規則合理安排ResourceStream的使用

  ● ResourceStream只是用于訪問應用程序和動態鏈接庫中的資源的

  在Classes在單元中提供了InternalReadComponentRes函數,該函數使用了TResourceStream對象從Delphi應用程序中讀取部件。Delphi是將窗體和部件信息放在模塊資源的RCDATA段的。

  20.1.7 TBlobStream對象

  從Delphi 數據庫開發平臺這個意義上說,TBlobStream 對象是個很重要的對象。TBlobStream對象提供了修改TBlobField、TBytesField或TVarBytesField中數據的技術。開發者可以象對待文件或流那樣在數據庫域中讀寫數據。

  傳統數據庫發展的一個重要趨向是往多媒體數據庫發展。目前比較著名和流行的數據庫都支持多媒體功能,多媒體數據存儲中的一大難點是數據結構不規則,數據量大。各大數據庫產品是采用BLOB技術解決多媒體數據存儲中的問題。Delphi的TBlobStream對象的意義就在于:一方面可以使Delphi應用程序充分利用多媒體數據庫的數據管理能力;另一方面又能利用Object Pascal的強大程序設計能力給多媒體數據庫提供全方向的功能擴展余地。

  使用TBlobStream對象可以在多媒體數據庫的BLOB字段存儲任意格式的數據。一般說來,許多多媒體數據庫只能支持圖像、語音或者OLE服務器支持的數據。利用TBlobStream則不同,只要是程序能夠定義的數據格式,它都能在BLOB字段中讀寫,而不需要其它輔助工具。

  TBlobStream用構造方法Create建立數據庫域和BLOB流的聯接。用Read或Write 方法訪問和改變域中的內容;用Seek方法,在域中定位;用Truncate方法刪除域中當前位置起所有的數據。

  20.1.7.1 TBlobStream的屬性和方法

  TBlobStream對象從TStream直接繼承,沒有增添新的屬性。它覆蓋了Read、Write 和Seek方法,提供了對BLOB字段的訪問操作;它增添了Truncate方法以實現BLOB字段中的刪除操作。

  1. Read方法

  聲明:function Read(var Buffer; Count: Longint): Longint;

  Read方法從數據庫域的當前位置起復制Count個字節的內容到Buffer中。Buffer也必須至少分配Count個字節。Read方法返回實際傳輸的字節數,因為傳輸的字節數可能小于Count,所以需要選擇符的邊界判斷。

  2. Write方法

  聲明:function Write(const Buffer; Count: Longint); override; Longint;

  Write方法從Buffer中向數據庫域的當前位置復制Count個字節的內容。Buffer必須分配有Count個字節的內存空間,函數返回實際傳輸的字節數,傳輸過程也要進行選擇符邊界判斷。

  3. Seek方法

  聲明:function Seek(Offset: Longint; Origin: Word): Longint;

  Seek方法重新設置BLOB流中的指針位置。如果Origin的值是soFromBeginning,則新的指針位置是Offset; 如Origin的值是soFromCurrent,則新的指針位置是Position+Offset;如果Origin的值是SoFromCurrent,則新的指針位置是Size+Offset。函數返回新的指針位置值。當Origin為0(SoFromBegin)時,Offset的值必須大于等于零; 當Origin的值為2(SoFromEnd),Offset的值必須小于等于零。

  4. Truncate方法

  聲明:procedure Truncate;

  Truncate方法撤消TBlobField、TBytesField或TVarBytesField中從當前位置起的數據。

  5. Create方法

  聲明:constructor Create(Field: TBlobField; Mode: TBlobStreamMode);

  Create方法使用Field參數建立BLOB流與BLOB字段的聯接。Mode 的值可為bmRead、bmWrite和bmReadWrite。

  20.1.7.2 TBlobStream的實現原理

  說明TBlobStream對象的實現原理,不可避免地要涉及它的私有域,下面是私有域的定義:

  TBlobStream = class(TStream)

  private

  FField: TBlobField;

  FDataSet: TDataSet;

  FRecord: PChar;

  FBuffer: PChar;

  FFieldNo: Integer;

  FOpened: Boolean;

  FModified: Boolean;

  FPosition: Longint;

  …

  public

  …

  end;

  FField是與BLOB流相聯的數據庫BLOB域,該域用于BLOB流的內部訪問。FDataSet是代表FField所在的數據庫,它可以是TTable部件,也可以是TQuery 部件。FRecord和FBuffer都是BLOB流內部使用的緩沖區,用于存儲FField所在記錄的數據,該數據記錄中不包含BLOB數據,TBlobStream使用FRecord作為調用BDE API函數的參數值。FFieldNo代表BLOB字段的字段號,也用于BDE API的參數傳遞,FOpened和FMocified都是狀態信息,FPosition表示BLOB流的當前位置,下面介紹TBlobStream方法實現。

  1. Create方法和Destroy方法的實現

  Create方法的功能主要是建立BlobStream流與BLOB字段的聯系并初始化某些私有變量。其實現如下:

  constructor TBlobStream.Create(Field: TBlobField; Mode: TBlobStreamMode);

  var

  OpenMode: DbiOpenMode;

  begin

  FField := Field;

  FDataSet := Field.DataSet;

  FRecord := FDataSet.ActiveBuffer;

  FFieldNo := Field.FieldNo;

  if FDataSet.State = dsFilter then

  DBErrorFmt(SNoFieldAccess, [FField.DisplayName]);

  if not FField.FModified then

  begin

  if Mode = bmRead then

  begin

  FBuffer := AllocMem(FDataSet.RecordSize);

  FRecord := FBuffer;

  if not FDataSet.GetCurrentRecord(FBuffer) then Exit;

  OpenMode := dbiReadOnly;

  end else

  begin

  if not (FDataSet.State in [dsEdit, dsInsert]) then DBError(SNotEditing);

  OpenMode := dbiReadWrite;

  end;

  Check(DbiOpenBlob(FDataSet.Handle, FRecord, FFieldNo, OpenMode));

  end;

  FOpened := True;

  if Mode = bmWrite then Truncate;

  end;

  該方法首先是用傳入的Field參數給FField,FDataSet,FRecord和FFieldNo賦值。方法中用AllocMem按當前記錄大小分配內存,并將指針賦給FBuffer,用DataSet部件的GetCurrentRecord方法,將記錄的值賦給FBuffer,但不包括BLOB數據。

  方法中用到的DbiOpenBlob函數是BDE的API函數,該函數用于打開數據庫中的BLOB字段。

  最后如果方法傳入的Mode參數值為bmWrite,就調用Truncate將當前位置指針以后的

  數據刪除。

  分析這段源程序不難知道:

  ● 讀寫BLOB字段,不允許BLOB字段所在DataSet部件有Filter,否則產生異常事件

  ● 要讀寫BLOB字段,必須將DataSet設為編輯或插入狀態

  ● 如果BLOB字段中的數據作了修改,則在創建BLOB 流時,不再重新調用DBiOpenBlob函數,而只是簡單地將FOpened置為True,這樣可以用多個BLOB 流對同一個BLOB字段讀寫

  Destroy方法釋放BLOB字段和為FBuffer分配的緩沖區,其實現如下:

  destructor TBlobStream.Destroy;

  begin

  if FOpened then

  begin

  if FModified then FField.FModified := True;

  if not FField.FModified then

  DbiFreeBlob(FDataSet.Handle, FRecord, FFieldNo);

  end;

  if FBuffer <> nil then FreeMem(FBuffer, FDataSet.RecordSize);

  if FModified then

  try

  FField.DataChanged;

  except

  Application.HandleException(Self);

  end;

  end;

  如果BLOB流中的數據作了修改,就將FField的FModified置為True;如果FField的Modified為False就釋放BLOB字段,如果FBuffer不為空,則釋放臨時內存。最后根據FModified的值來決定是否啟動FField的事件處理過程DataChanged。

  不難看出,如果BLOB字段作了修改就不釋放BLOB字段,并且對BLOB 字段的修改只有到Destroy時才提交,這是因為讀寫BLOB字段時都避開了FField,而直接調用BDE API函數。這一點是在應用BDE API編程中很重要,即一定要修改相應數據庫部件的狀態。

  2. Read和Write方法的實現

  Read和Write方法都調用BDE API函數完成數據庫BLOB字段的讀寫,其實現如下:

  function TBlobStream.Read(var Buffer; Count: Longint): Longint;

  var

  Status: DBIResult;

  begin

  Result := 0;

  if FOpened then

  begin

  Status := DbiGetBlob(FDataSet.Handle, FRecord, FFieldNo, FPosition,

  Count, @Buffer, Result);

  case Status of

  DBIERR_NONE, DBIERR_ENDOFBLOB:

  begin

  if FField.FTransliterate then

  NativeToAnsiBuf(FDataSet.Locale, @Buffer, @Buffer, Result);

  Inc(FPosition, Result);

  end;

  DBIERR_INVALIDBLOBOFFSET:

  {Nothing};

  else

  DbiError(Status);

  end;

  end;

  end;

上一頁  1 2 3 4 5 6 7 8 9 下一頁
  相關推薦:2010年9月計算機等級考試試題及答案解析專題
       預告:名師解析2010年9月計算機等級考試試題答案
       2010年9月計算機等級考試成績查詢時間及入口
       2010年9月計算機等考成績查詢短信免費提醒開通
文章搜索
版權聲明:如果計算機等級考試網所轉載內容不慎侵犯了您的權益,請與我們聯系800@exam8.com,我們將會及時處理。如轉載本計算機等級考試網內容,請注明出處。
主站蜘蛛池模板: 亚洲免费人成在线视频观看 | 欧美大成色www永久网站婷 | 97国产成人精品免费视频 | 奇米影视亚洲狠狠色777不卡 | 美女一级牲交毛片视频 | 欧美亚洲欧美区 | h片在线播放免费高清 | 成人在线观看播放 | 欧美又粗又硬又大久久久 | 在线亚洲精品国产波多野结衣 | 亚洲最大在线观看 | 成人片在线看 | 一区二区精品视频 | 午夜影院视频 | 国产成人啪精品 | 欧美91| 在线观看a视频 | 日韩精品午夜视频一区二区三区 | 波多野结衣中文字幕在线 | 国产精品h片在线播放 | 一级aaaaaa片毛片在线播放 | 欧美日韩在线免费观看 | 正在播放国产一区 | 怡红院免费手机在线观看 | 久久91精品久久久久久水蜜桃 | 好吊色几万部永久免费视频 | 欧美日韩一区二区三区高清不卡 | 亚州综合网| 国产伦精品一区二区三区免 | 欧美一区二区三区四区视频 | 国产黄色影院 | 性刺激欧美三级在线现看中文 | 丝袜美脚在线 | 扒开双腿爽爽爽视频www | 五月婷在线 | 狠狠狠狠狠狠 | 国产成人永久在线播放 | 欧美精品一区二区久久 | 污91视频 | 欧美成人免费观看久久 | 日本免费全黄一级裸片视频 |