程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> Delphi流操作技巧總結

Delphi流操作技巧總結

編輯:Delphi
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;

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved