国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

對TMemoryStream的一些改進

2019-11-18 18:07:02
字體:
供稿:網(wǎng)友
怎么又是關(guān)于Stream的,呵呵,應(yīng)該說只是最近比較關(guān)心程序的效率問題,而我對Stream其實并沒有什么特別的研究,只是自己發(fā)現(xiàn)了一些新的用法,希望能對大家有用而已。

事情的起因還是那個破爛電子相冊軟件,今天又發(fā)現(xiàn)了一個可改進之處,有一段程序我原來是這么寫的:
PRocedure CreateFile(const AFileName:String;const AStream:TMemoryStream);
var
  FileStream:TMemoryStream;
begin
  ShowProgressForm(nil);
  FileStream:=TMemoryStream.Create();
  try
    FileStream.LoadFromFile(AFileName);
    FileStream.Position:=FileStream.Size;
    AStream.Position:=0;
    FileStream.CopyFrom(AStream,AStream.Size);
    FileStream.SaveToFile(AFileName);
  finally
    FileStream.Free;
  end;
end;
為了完成將一個TMemoryStream追加到一個文件中的任務(wù),我使用了另一個TMemoryStream,讓它先打開文件,然后使用CopyFrom()函數(shù),從原始Stream中加入數(shù)據(jù),最后再保存到文件中。
其中最糟糕的就是CopyFrom()函數(shù),它會開辟一塊新的內(nèi)存,先調(diào)用ReadBuffer()函數(shù),從源Stream中取得數(shù)據(jù),再調(diào)用自身的WriteBuffer()函數(shù),寫到自身的Buffer中,最后再釋放這塊臨時內(nèi)存,這些過程可以看這段代碼:
function TStream.CopyFrom(Source: TStream; Count: Int64): Int64;
const
  MaxBufSize = $F000;
var
  BufSize, N: Integer;
  Buffer: PChar;
begin
  if Count = 0 then
  begin
    Source.Position := 0;
    Count := Source.Size;
  end;
  Result := Count;
  if Count > MaxBufSize then BufSize := MaxBufSize else BufSize := Count;
  GetMem(Buffer, BufSize);
  try
    while Count <> 0 do
    begin
      if Count > BufSize then N := BufSize else N := Count;
      Source.ReadBuffer(Buffer^, N);
      WriteBuffer(Buffer^, N);
      Dec(Count, N);
    end;
  finally
    FreeMem(Buffer, BufSize);
  end;
end;
而且,不知道為何,Delphi自己提供的Move()函數(shù)在內(nèi)存拷貝時顯得特別的慢。最后導(dǎo)致的結(jié)果就是,我在將30MB左右的數(shù)據(jù)寫入文件時,會花半分鐘的時間。

知道了問題所在,那么要加速這個過程就很簡單了,首先當(dāng)然要避免內(nèi)存拷貝,所以我決心去掉那個累贅的FileStream,讓原始Stream自己將內(nèi)存數(shù)據(jù)寫入到文件,那樣不是就可以了嗎?
但是無論是TMemoryStream,還是TFileStream,都只提供將數(shù)據(jù)完全寫入一個文件的功能,而我需要的則是追加功能,呵呵,這個簡單,自己打開文件,然后WriteFile()就可以了,所以最終的解決方法就是:
從TMemoryStream繼承出一個新類,暫且叫做TMemoryStreamEx,加入一個新的方法,叫做:AppendToFile(),可以將內(nèi)存數(shù)據(jù)完全追加到已存在的文件內(nèi),函數(shù)內(nèi)容如下:
procedure TMemoryStreamEx.AppendToFile(const AFileName:String);
var
  FileHandle:LongWord;
  CurPos:LongWord;
  BytesWritten:LongWord;
begin
  FileHandle:=CreateFile(PChar(AFileName),GENERIC_WRITE,0,nil,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
  if FileHandle=INVALID_HANDLE_VALUE then begin
    raise MemoryStreamExException.Create('Error when create file');
  end;
  try
    CurPos:=SetFilePointer(FileHandle,0,nil,FILE_END);
    LockFile(FileHandle,CurPos,0,Size,0);
    try
      BytesWritten:=0;
      if not WriteFile(FileHandle,Memory^,Size,BytesWritten,nil) then begin
        raise MemoryStreamExException.Create('Error when write file');
      end;
      if (Size<>BytesWritten) then begin
        raise MemoryStreamExException.Create('Wrong written size');
      end;
    finally
      UnlockFile(FileHandle,CurPos,0,Size,0);
    end;
  finally
    CloseHandle(FileHandle);
  end;
end;

好了,替換掉原來的那段程序,新的程序變?yōu)椋?BR>procedure TExeExporter.CreateExecutableFile(const AFileName:String;const AStream:TMemoryStreamEx);
begin
  AStream.AppendToFile(AFileName);
end;
就那么簡單,速度也縮短到僅僅2-3秒了。

最近單位做的一系列軟件也在進行提速優(yōu)化,使用了好多方法,自己管理內(nèi)存(減少malloc的調(diào)用次數(shù)),使用HashTable存放經(jīng)常要進行查找的數(shù)據(jù)。。。。等等,看到自己開發(fā)的軟件在速度上有了質(zhì)的飛躍,實在是很有成就感啊。

 


上一篇:IntToHex(10-16進制的轉(zhuǎn)換)

下一篇:MPEG音頻壓縮規(guī)格一覽

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
學(xué)習(xí)交流
熱門圖片

新聞熱點

疑難解答

圖片精選

網(wǎng)友關(guān)注

主站蜘蛛池模板: 东辽县| 廊坊市| 普安县| 青龙| 汕尾市| 宣武区| 淅川县| 渝北区| 南昌市| 陵水| 萝北县| 临漳县| 巫山县| 新河县| 砚山县| 吉木乃县| 天祝| 安平县| 民和| 云梦县| 江永县| 阿瓦提县| 湘乡市| 泾源县| 巫山县| 朝阳区| 阳春市| 张家口市| 临桂县| 青海省| 陵水| 镇雄县| 秀山| 安康市| 新竹市| 江门市| 永修县| 民勤县| 嵊州市| 儋州市| 类乌齐县|