TMemoryStream的繼承關係如下
TObject
|
TStream
|
TCustomMemoryStream
|
TMemoryStream
如何使用TMemoryStream?
其實TmemoryStream使用就跟TStream 一樣
具體的屬性,方法可看幫助。
下舉一例:
如我想在記憶體中直接讀寫一個Bitmap,怎麼辦?
TmemoryStream幫了你大忙
var
BitmapMemoryStream:TMemoryStream;
Bitmap1:TBitmap;
PRocedure TForm.Button1Click(Sender:TObject);
begin
BitmapmemroyStream:=TmemoryStream.Create; file://建立MemoryStream
Bitmap1:=TBitmap.Create;
try
Bitmap1.LoadFromFile('d:Bitmap1.bmp');
except
ShowMessage('Error On LoadFile bitmap1.bmp');
end;
end;
procedure TForm.Button2Click(Sneder:Tobject);
begin
if Assigned(Bitmap1) then
Bitmap1.SaveToStream(BitmapmemoryStream);
end;
procedure TForm.Button3Click(Sender:TObject);
begin
if BitmapMemoryStream<>nil then
begin
try
BitmapMemroyStream.SaveToFile('Bitmap1.str'); file://記憶體流保存,大小與
file://Bitmap1.bmp一樣
except
showmessage('error on access memory!');
end;
end;
end;
procedure TForm.Button4Click(Sender:TObject);
var
Buffer:Array[0..53] of char;
begin
if Assigned( BitmapMemroyStream) then
try
BitmapMemroyStream.Seek(0,soFromBeginning);
BitmapMemoryStream.Read(Buffer,54);
if Buffer[0]='B' and Buffer[1]='M' then file://改寫記憶體內容
begin
BitmapMemoryStream.Seek(0,soFromBeginning);
BitmapmemoryStream.Write('ICE',3);
Button3Click(Sender);//將改寫的內容寫入文件
end;
except
ShowMessage('error On Access memroyStream');
end;
end;
大家可看到用TMemoryStream對與記憶體讀寫多麼方便,當然其實用不著先建一Bitmap
可以用LoadFromFile直接引導文件,但是如果對於其它的記憶體流卻是可以用上述方法
上文只是拋轉引玉,其它的一些功能大家可以看幫助,自己琢磨!
還有很多其它的流式對象,大致差不多,一通百通!
如何將一個流的內容寫入到剪貼簿中,並處理
這個技巧是參考Delphi的剪貼簿類別的實作來完成的。將一個串流的內容放入剪貼簿,
首先要註冊你自已的格式,使用RegisterClipboardFormat()函數
然後做下面三步:
1.建立一個內容流,並將內容寫進去
2.建立一個全域的內容區,並將流的內容寫入
3.呼叫ClipBoard.SetAsHandle()將內容寫入剪貼簿
將內容寫入剪貼簿中
var
hbuf : THandle;
bufptr : Pointer;
mstream : TMemoryStream;
begin
mstream := TMemoryStream.Create;
try
{-- 處理流程的程式碼--}
hbuf := GlobalAlloc(GMEM_MOVEABLE, mstream.size);
try
bufptr := GlobalLock(hbuf);
try
Move(mstream.Memory^, bufptr^, mstream.size);
Clipboard.SetAsHandle(CF_MYFORMAT, hbuf);
finally
GlobalUnlock(hbuf);
end;
except
GlobalFree(hbuf);
raise;
end;
finally
mstream.Free;
end;
end;
請注意不要將分配的全域緩衝區釋放,這個工作由剪貼簿來完成,在讀出資料中
你應該將它複製後處理。
將剪貼簿內容讀出來
var
hbuf : THandle;
bufptr : Pointer;
mstream : TMemoryStream;
begin
hbuf := Clipboard.GetAsHandle(CF_MYFORMAT);
if hbuf <> 0 then begin
bufptr := GlobalLock(hbuf);
if bufptr <> nil then begin
try
mstream := TMemoryStream.Create;
try
mstream.WriteBuffer(bufptr^, GlobalSize(hbuf));
mstream.Position := 0;
{-- 處理流程的程式碼--}
finally
mstream.Free;
end;
finally
GlobalUnlock(hbuf);
end;
end;
end;
end;
在Dephi中使用TStream讀寫資料的技巧
在Dephi中提供了一個抽象的資料型別TStream來支援對流式資料的操作。這些資料通常來自檔案、資料庫、記憶體物件、OLE物件等,TStream提供了統一、簡潔的方法來進行資料的讀寫。在通常情況下,我們並不需要直接使用TStream類,對流式資料的讀寫封裝在VCL控制項的方法中。但是如果這些方法無法滿足我們的要求,就需要自己手動控制資料的讀寫。
一、 TStream的常用的方法與屬性:
---- 1. function Read(var Buffer; Count: Longint): Longint; virtual; abstract
---- 2. function Write(const Buffer; Count: Longint): Longint; virtual; abstract;
---- 3. function Seek(Offset: Longint; Origin: Word): Longint; virtual; abstract;
---- 4. property Position: Longint;
---- 5. property Size: Longint
---- Read,Write,Seek都是純虛函數,提供了資料讀寫和定位的抽象的方法。 Read方法將資料從Stream中讀到Buffer緩衝區中,Write則實作相反的操作,回傳值表示實際讀寫資料的大小。 Seek提供了在Stream中移動資料指標的方法。參數Origin可以取soFromBeginning,soFromCurrent,soFromEnd 三個值,Offset是偏移量,回傳值是目前Stream資料指標的位置。
---- Position表示了資料指標在Stream中的位置。這個屬性是可讀寫的,它其實就是透過呼叫Seek方法來實現的,所以實際使用時使用這個屬性會比較方便一些。 Size屬性表示目前Stream的大小,對於不同的Stream,有些時候是唯讀的。
二、 Stream資料的讀寫。
---- 1. SaveToStream(Stream: TStream ); file://將類別中的資料寫到Stream的目前位置中
---- 2. LoadFromStream(Stream: TStream); file://從目前位置讀入Stream裡的數據
---- 實際使用時我們基本上只要使用上面兩個函數就可以了。
三、 例子
---- TStream的繼承樹圖如圖1所示(略),實際使用時比較常用的是TFileStream,TMemoryStream,TblobStream,就以這三種流舉一例說明具體用法。
---- 建立一個窗體Form1,放置三個按鈕btnRead,btnInvert,btnSave和一個檔案開啟對話框OpenDialog1以及資料控制項DataSource1,Table1,test.
---- 使用Dephi提供的Database Desktop建立一個表test,表裡有一個字段域Image,資料庫檔案名稱存為test.db。在窗體上放置一個TDatabase控制項dbTest,一個TTable控制項Table1,一個DataSource控制項DataSource1,一個TDBNavigator控制項DBNavigator1。將dbTest與剛才Desktop建立的資料庫相連,Table1的TableName屬性設為test.db,DataSource1的DataSet屬性設為Table1,DBNavigator1的DataSource屬性設為DataSource1,VisibleButtons屬性前四個設為TRUE。此外,將dbtest的Connected設為TRUE,Table1的Active屬性設為TRUE,使得資料庫一開始就處於開啟狀態。
---- 事件程式碼寫如下:
---- 1. btnRead的Click事件,這裡示範了TFileStream的用法。
var
MS: TFileStream;
begin
if OpenDialog1.Execute then
begin
MS:=TFileStream.Create
(OpenDialog1.FileName, fmOpenRead);
Image1.Picture.Bitmap.LoadFromStream(MS);
MS.Free;
end;
end;
---- 2. btnInvert的Click事件,這裡示範了TMemoryStream的用法。其中使用了Invert函數,這是一個簡單的將圖象反色的函數(僅對真彩圖像有效),它傳回一個指向處理過的圖象資料塊的指標。
var
M
S: TMemoryStream;
pImage: pointer;
begin
MS:=TMemoryStream.create;
Image1.Picture.Bitmap.SaveToStream(MS);
MS.Position:=0;
pImage:=Invert(MS.Memory, MS.size);
file://Memory屬性是指向實際記憶體區塊的指針
MS.Write(pImage^,MS.size);
MS.Position:=0;
file://上一行程式碼使指標移到了Stream末尾,所以要重設
Image1.Picture.Bitmap.LoadFromStream(MS);
FreeMem(pImage);
MS.Free;
end;
Invert函數如下:
function TForm1.Invert
(pImage: pointer; size: Integer): pointer;
var
pData, pMem: PChar;
i: Integer;
begin
pMem:=AllocMem(size);
CopyMemory(pMem,pImage,size);
pData:=pMem+54;
for i:=0 to size-54-1 do
begin
pData^:=Char(not integer(pData^));
pData:=pData+1;
end;
Result:=pMem;
end;
---- 1. btnSave的Click事件,這裡示範了TMemoryStream的另一種用法,將Stream中的資料寫到資料庫中去。
var
MS: TMemoryStream;
begin
MS:=TMemoryStream.create;
Image1.Picture.Bitmap.SaveToStream(MS);
MS.Position:=0;
Table1.Append;
file://在資料庫中新增一筆記錄
TBlobField(Table1.FieldbyName
('image')).LoadFromStream(MS);
Table1.Post;
file://將所做的更新寫入資料庫
end;
---- 4. DBNavigator1的Click事件,這裡示範了TBlobStream的用法,使用了和寫入時不同的方法來讀出資料庫的圖象資料。
var
MS: TStream;
begin
with Table1 do
MS:=CreateBlobStream
(FieldbyName('image'),bmRead);
Image1.Picture.Bitmap.
LoadFromStream(MS);
MS.Free;
end;
全文完,謝謝你讀了這篇文章。本人缺乏可用分了,只好來賺點參與分好兌換。如感覺此文對你有幫助的朋友請投我一票,謝謝。