在线现看午夜福利片|女人16久久免费视频|鲁丝片一区鲁丝片二区鲁丝|一区二区三区欧美在线

  1. 
    
    <b id="glvx9"></b>
        1. <blockquote id="glvx9"><meter id="glvx9"></meter></blockquote>
            首頁 考試吧論壇 Exam8視線 考試商城 網(wǎng)絡(luò)課程 模擬考試 考友錄 實用文檔 求職招聘 論文下載
            2011中考 | 2011高考 | 2012考研 | 考研培訓(xùn) | 在職研 | 自學(xué)考試 | 成人高考 | 法律碩士 | MBA考試
            MPA考試 | 中科院
            四六級 | 職稱英語 | 商務(wù)英語 | 公共英語 | 托福 | 雅思 | 專四專八 | 口譯筆譯 | 博思 | GRE GMAT
            新概念英語 | 成人英語三級 | 申碩英語 | 攻碩英語 | 職稱日語 | 日語學(xué)習(xí) | 法語 | 德語 | 韓語
            計算機等級考試 | 軟件水平考試 | 職稱計算機 | 微軟認(rèn)證 | 思科認(rèn)證 | Oracle認(rèn)證 | Linux認(rèn)證
            華為認(rèn)證 | Java認(rèn)證
            公務(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)紀(jì)人 | 投資項目管理師 | 土地登記代理人 | 環(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)用是很重要的。

              2. TMemoryStream對象方法的實現(xiàn)

              ⑴ Realloc方法

              Realloc方法是TMemoryStream動態(tài)內(nèi)存分配的核心,它的SetSize、SetCapacity等方法最終都是調(diào)用Realloc進行內(nèi)存的分配和初始化工作的。它的實現(xiàn)如下:

              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為單位分配動態(tài)內(nèi)存的,方法中的第一句if語句就是執(zhí)行該操作。如果傳入的NewCapacity參數(shù)值為0,則釋放流中的內(nèi)存。Realloc方法用GLobal FreePtr函數(shù)釋放內(nèi)存,用GlobalAllocPtr分配內(nèi)存,用GlobalReallocPtr進行內(nèi)存的重分配。如果原來的Capacity屬性值為0,則調(diào)用Globa|AllocPtr否則調(diào)用GlobalReallocPtr。最后如果Result為nil則觸發(fā)內(nèi)存流錯的異常事件,否則返回指向分配的內(nèi)存的指針。

              ⑵ Write方法

              Write方法從內(nèi)存流內(nèi)部緩沖池的當(dāng)前位置開始寫入二進制數(shù)據(jù)。其實現(xiàn)如下:

              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中存儲要寫入流的二進制數(shù)據(jù),如果要寫入的數(shù)據(jù)的字節(jié)超出了流的內(nèi)存池的大小,則調(diào)用SetCapacity方法再分配內(nèi)存,然后用內(nèi)存復(fù)制函數(shù)將Buffer中的數(shù)據(jù)復(fù)制到FMemory中。接著移動位置指針,并返回寫入數(shù)據(jù)的字節(jié)數(shù)。分析這段程序可以知道,F(xiàn)Capacity的值和FSize的值是不同的。

              ⑶ Clear方法

              Clear方法消除內(nèi)存流中的數(shù)據(jù),將Memory屬性置為nil,并將FSize和FPosition 的值設(shè)為0。其實現(xiàn)如下:

              procedure TMemoryStream.Clear;

              begin

              SetCapacity(0);

              FSize := 0;

              FPosition := 0;

              end;

             、 LoadFromStream和LoadFromFile方法

              LoadFromStream方法首先根據(jù)傳入的Stream的Size屬性值重新分配動態(tài)內(nèi)存,然后調(diào)用Stream的ReadBuffer方法往FMemory中復(fù)制數(shù)據(jù),結(jié)果Stream的全部內(nèi)容在內(nèi)存中有了一份完整拷貝。其實現(xiàn)如下:

              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首先創(chuàng)建了一個TFileStream對象,然后調(diào)用LoadFromStream方法,將FileStream文件流中的數(shù)據(jù)寫入MemoryStream中。

              20.1.6 TResourceStream對象

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

              下面介紹TResourceStream的實現(xiàn)

              1. 私有域

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

              TResourceStream = class(TCustomMemoryStream)

              private

              HResInfo: HRSRC;

              HGlobal: THandle;

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

              …

              end;

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

              Initialize方法是TResourceStream對象內(nèi)部使用的。它的構(gòu)造方法Create和CreateFromID都是調(diào)用Initialize方法完成對TResourceStream的初始化。它的實現(xiàn)如下:

              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;

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

              2. 構(gòu)造方法Create和CreateFromID

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

              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參數(shù),該參數(shù)值的含義在Insitialize中介紹過。

              3. Write方法

              TResourceStream的Write方法只完成一件事,就產(chǎn)生這個異常事件,其實現(xiàn)如下:

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

              begin

              raise EStreamError.CreateRes(SCantWriteResourceStreamError);

              end;

              從方法實現(xiàn)中可以看到,TSourceStream對象是不允許寫數(shù)據(jù)的。一旦往資源流中寫數(shù)據(jù)將產(chǎn)生異常事件。

              4. 析構(gòu)方法Destroy

              該方法產(chǎn)生給資源解鎖,然后釋放該資源,最后調(diào)用繼承的Destroy方法釋放ResourceStream。其實現(xiàn)如下:

              destructor TResourceStream.Destroy;

              begin

              UnlockResource(HGlobal);

              FreeResource(HResInfo);

              inherited Destroy;

              end;

              回顧Initialize方法,我們不難發(fā)現(xiàn):

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

              ● ResourceStream中的資源在流的生存期,始終是Lock狀態(tài),因此要根據(jù)Windows 的內(nèi)存使用規(guī)則合理安排ResourceStream的使用

              ● ResourceStream只是用于訪問應(yīng)用程序和動態(tài)鏈接庫中的資源的

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

              20.1.7 TBlobStream對象

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

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

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

              TBlobStream用構(gòu)造方法Create建立數(shù)據(jù)庫域和BLOB流的聯(lián)接。用Read或Write 方法訪問和改變域中的內(nèi)容;用Seek方法,在域中定位;用Truncate方法刪除域中當(dāng)前位置起所有的數(shù)據(jù)。

              20.1.7.1 TBlobStream的屬性和方法

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

              1. Read方法

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

              Read方法從數(shù)據(jù)庫域的當(dāng)前位置起復(fù)制Count個字節(jié)的內(nèi)容到Buffer中。Buffer也必須至少分配Count個字節(jié)。Read方法返回實際傳輸?shù)淖止?jié)數(shù),因為傳輸?shù)淖止?jié)數(shù)可能小于Count,所以需要選擇符的邊界判斷。

              2. Write方法

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

              Write方法從Buffer中向數(shù)據(jù)庫域的當(dāng)前位置復(fù)制Count個字節(jié)的內(nèi)容。Buffer必須分配有Count個字節(jié)的內(nèi)存空間,函數(shù)返回實際傳輸?shù)淖止?jié)數(shù),傳輸過程也要進行選擇符邊界判斷。

              3. Seek方法

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

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

              4. Truncate方法

              聲明:procedure Truncate;

              Truncate方法撤消TBlobField、TBytesField或TVarBytesField中從當(dāng)前位置起的數(shù)據(jù)。

              5. Create方法

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

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

              20.1.7.2 TBlobStream的實現(xiàn)原理

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

              TBlobStream = class(TStream)

              private

              FField: TBlobField;

              FDataSet: TDataSet;

              FRecord: PChar;

              FBuffer: PChar;

              FFieldNo: Integer;

              FOpened: Boolean;

              FModified: Boolean;

              FPosition: Longint;

              …

              public

              …

              end;

              FField是與BLOB流相聯(lián)的數(shù)據(jù)庫BLOB域,該域用于BLOB流的內(nèi)部訪問。FDataSet是代表FField所在的數(shù)據(jù)庫,它可以是TTable部件,也可以是TQuery 部件。FRecord和FBuffer都是BLOB流內(nèi)部使用的緩沖區(qū),用于存儲FField所在記錄的數(shù)據(jù),該數(shù)據(jù)記錄中不包含BLOB數(shù)據(jù),TBlobStream使用FRecord作為調(diào)用BDE API函數(shù)的參數(shù)值。FFieldNo代表BLOB字段的字段號,也用于BDE API的參數(shù)傳遞,F(xiàn)Opened和FMocified都是狀態(tài)信息,F(xiàn)Position表示BLOB流的當(dāng)前位置,下面介紹TBlobStream方法實現(xiàn)。

              1. Create方法和Destroy方法的實現(xiàn)

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

              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參數(shù)給FField,F(xiàn)DataSet,F(xiàn)Record和FFieldNo賦值。方法中用AllocMem按當(dāng)前記錄大小分配內(nèi)存,并將指針賦給FBuffer,用DataSet部件的GetCurrentRecord方法,將記錄的值賦給FBuffer,但不包括BLOB數(shù)據(jù)。

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

              最后如果方法傳入的Mode參數(shù)值為bmWrite,就調(diào)用Truncate將當(dāng)前位置指針以后的

              數(shù)據(jù)刪除。

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

              ● 讀寫B(tài)LOB字段,不允許BLOB字段所在DataSet部件有Filter,否則產(chǎn)生異常事件

              ● 要讀寫B(tài)LOB字段,必須將DataSet設(shè)為編輯或插入狀態(tài)

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

              Destroy方法釋放BLOB字段和為FBuffer分配的緩沖區(qū),其實現(xiàn)如下:

              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流中的數(shù)據(jù)作了修改,就將FField的FModified置為True;如果FField的Modified為False就釋放BLOB字段,如果FBuffer不為空,則釋放臨時內(nèi)存。最后根據(jù)FModified的值來決定是否啟動FField的事件處理過程DataChanged。

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

              2. Read和Write方法的實現(xiàn)

              Read和Write方法都調(diào)用BDE API函數(shù)完成數(shù)據(jù)庫BLOB字段的讀寫,其實現(xiàn)如下:

              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 下一頁
              相關(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)容,請注明出處。