20.3.2.4 BLOB字段與Stream對象
因為Delphi中,BLOB字段是通過BLOB流來訪問的,所以可以很容易地在BLOB字段和Stream對象之間傳遞數據。為此,TBlobField對象提供了LoadFromStream和SaveToStream方法。
procedure TBlobField.LoadFromStream(Stream: TStream);
var
BlobStream: TBlobStream;
begin
BlobStream := TBlobStream.Create(Self, bmWrite);
try
BlobStream.CopyFrom(Stream, 0);
finally
BlobStream.Free;
end;
end;
procedure TBlobField.SaveToStream(Stream: TStream);
var
BlobStream: TBlobStream;
begin
BlobStream := TBlobStream.Create(Self, bmRead);
try
Stream.CopyFrom(BlobStream, 0);
finally
BlobStream.Free;
end;
end;
20.3.3 存取嵌入在OleContainer對象中的OLE服務器的數據
對象鏈接和嵌入(Object Linking and Embedding,簡稱OLE),是一組服務功能,它提供了一種用來源於不同應用程序的信息創建復合文檔的強有力方法。
通過把圖像、圖形、表格、聲音、注解、文件和其它表示手段描述成對象,用它能在不同軟件廠家提供的應用程序中更為容易地交換合成和處理數據它是應用程序的集成更為容易。OLE2.0支持直觀編輯。用戶不需切換到不同窗口就能在文檔中直接對對象進行操作,改進了操作環境。用戶不用再關注應用程序和操作環境,只需關注於使用對象技術的數據和文件,便能完成全部工作。
OLE已成為操作系統功能上的一大標准,各大軟商紛紛在開發工具中支持OLE 2.0規范。Delphi 2.0提供了OleContainer對象支持OLE窗戶應用程序的開發。
盡管通過OLE可以用來源於不同應用程序的信息創建復合文檔,充分體現以任務、以文檔為中心的思想,但是很難分解來自其它應用程序中的嵌入數據,以進行特殊的處理。
例如,一套多媒體電子文檔管理系統,系統需要數據庫管理功能文檔編輯功能,全文檢索功能等。在文檔編輯功能的實現上,如果能利用中文Word 或寫字板之類的強大的編輯排版功能,就可以省卻重新開發一個文檔編輯的費用,使用具有直觀編輯的OLE復合文檔嵌入Word的DOC數據或RTF數據當然是最佳的選擇。 但問題在於全文檢索系統要求能直接在文檔中搜索關鍵字,因此要求將文檔數據從OLE嵌入數據或文檔中的本地數據中分離出來。
Delphi 2.0的OleContainer部件支持存儲OLE對象數據。OLE對象數據包括兩部分:OLE類描述信息和OLE服務器嵌入數據。一般說來,OLE服務器嵌入數據是以服務器支持的數據格式存儲的; 比方說,中文Word 6.0的嵌入數據的格式就是Word 6.0文檔的格式。因此,要將文檔數據從OLE 嵌入式文檔中分離出來就是要訪問第二部分數據。
我們分析了Delphi 2.0的OleContainer對象存取復合文檔的程序,得到分離數據的方法。
讓我們來看一段OleContainer對象存儲數據的程序:
procedure TOleContainer.SaveToStream(Stream: TStream);
var
DataHandle: HGlobal;
Buffer: Pointer;
Header: TStreamHeader;
R: TRect;
……
begin
……
try
……
if FOldStreamFormat then
begin
R := BoundsRect;
Header.PartRect.Left := R.Left;
Header.PartRect.Top := R.Top;
Header.PartRect.Right := R.Right;
Header.PartRect.Bottom := R.Bottom;
end else
begin
Header.Signature := StreamSignature;
Header.DrawAspect := FDrawAspect;
end;
Header.DataSize := GlobalSize(DataHandle);
Stream.WriteBuffer(Header, SizeOf(Header));
Buffer := GlobalLock(DataHandle);
try
Stream.WriteBuffer(Buffer^, Header.DataSize);
finally
GlobalUnlock(DataHandle);
end;
finally
ReleaseObject(TempStorage);
ReleaseObject(TempLockBytes);
end;
end;
程序中,OleContainer對象執行了兩次往流中寫數據的操作。
Stream.WriteBuffer(Header, Size(Header));
Stream.WriteBuffer(Buffer^, Header.DataSize);
前一語句是寫入OLE類描述信息,後一句語句是寫入OLE服務器的嵌入數據。Header是TStreamHeader記錄類型的變量。TStreamHeader記錄的定義如下:
TStreamHeader = record
case Integer of
0: ( { 新版OLE對象 }
Signature: Integer;
DrawAspect: Integer;
DataSize: Integer);
1: ( { 舊版OLE對象 }
PartRect: TSmallRect);
end;
因此讀OLE服務器嵌入數據時,要跳過文件頭的TStreamHeader記錄。下面就是如何分離OLE服務器嵌入數據的程序:
var
Stream : TMemoryStream;
FileStream : TFileStream;
begin
Stream := TMemoryStream.Create;
FileStream := TFileStream.Create('TEST.DOC', fmCreate) ;
with OleContainer1 do
if (State <> osEmpty) then
SaveToStream(Stream);
Stream.Seek(Sizeof(TStreamHeader), 0);
FileStream.CopyFrom(Stream, Stream.Size - SizeOf(TStreamHeader));
Stream.Free;
FileStream.Free;
end;
OleContainer1包含的服務器對象是中文Word 6.0,程序中將分離出的數據存儲在磁盤文件“TEST.DOC”上。如果希望存儲在不同的媒介上,可以使用相應的Stream對象,分離的方法類似。但是,這種方法並非對所有的OLE服務器數據都適用,如Windows 95 附件中的寫字板(WordPad)就不行。