e股脑电脑教程网
  • 首 页
  • 操作系统
  • 应用软件
  • 下载工具
  • 影音视频
  • 办公软件
  • 媒体制作
  • 网站建设
  • 平面设计
  • 数据库
  • 程序开发
  • 视频教程
编辑推荐: | 文章搜索:
您现在的位置: e股脑 >> 程序开发 >> Delphi教程 >> 对TMemoryStream的一些改进 >> 教程正文
 
教程搜索
 
 
相关教程
  • 利用Delphi和金山词霸制作批量单词翻译
  • Delphi2005的使用感受
  • delphi2005启动加快
  • ShadowStarCodeFastV0.5支持HTML格式拷
  • Delphi组件编写--扑克牌组件
  • delphi7找不到TBDEClientDataSet控件的
  • 动态连接数据库及动态建立ODBC,DSN(ZT
  • DelphiINPUTHelperv1.5forDelphi2005
  • 如何显示子线程的当前状态
  • delphi调用sql-server2000存储过程
  • 对TMemoryStream的一些改进
  • ShadowStarCodeFast截图
  • 代码优化分析一例
  • Delphi中的属性property(适合初学del
  • 小知识:MPEG音频压缩规格一览
  • SQLServer注入工具1.0
 
 

图文教程


  • Windows抢了谁的饭碗 非主流操作系统To

  • 地球还是火星 平常心看“非主流”

  • 综合运用Office 2007批量制作奖状

  • 没有系统盘如何才能修复受损系统?

  • 巧妙运用Excel中边界的附加功能!
 
 
赞 助 商
 
 
对TMemoryStream的一些改进
  • 来源:e股脑
  • 点击次数:
  • 更新时间:2007-8-9

怎么又是关于Stream的,呵呵,应该说只是最近比较关心程序的效率问题,而我对Stream其实并没有什么特别的研究,只是自己发现了一些新的用法,希望能对大家有用而已。

事情的起因还是那个破烂电子相册软件,今天又发现了一个可改进之处,有一段程序我原来是这么写的:

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追加到一个文件中的任务,我使用了另一个TMemoryStream,让它先打开文件,然后使用CopyFrom()函数,从原始Stream中加入数据,最后再保存到文件中。

其中最糟糕的就是CopyFrom()函数,它会开辟一块新的内存,先调用ReadBuffer()函数,从源Stream中取得数据,再调用自身的WriteBuffer()函数,写到自身的Buffer中,最后再释放这块临时内存,这些过程可以看这段代码:

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()函数在内存拷贝时显得特别的慢。最后导致的结果就是,我在将30MB左右的数据写入文件时,会花半分钟的时间。

知道了问题所在,那么要加速这个过程就很简单了,首先当然要避免内存拷贝,所以我决心去掉那个累赘的FileStream,让原始Stream自己将内存数据写入到文件,那样不是就可以了吗?

但是无论是TMemoryStream,还是TFileStream,都只提供将数据完全写入一个文件的功能,而我需要的则是追加功能,呵呵,这个简单,自己打开文件,然后WriteFile()就可以了,所以最终的解决方法就是:

从TMemoryStream继承出一个新类,暂且叫做TMemoryStreamEx,加入一个新的方法,叫做:AppendToFile(),可以将内存数据完全追加到已存在的文件内,函数内容如下:

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;

好了,替换掉原来的那段程序,新的程序变为:

procedure TExeExporter.CreateExecutableFile(const AFileName:String;const AStream:TMemoryStreamEx);

begin

AStream.AppendToFile(AFileName);

end;

就那么简单,速度也缩短到仅仅2-3秒了。

最近单位做的一系列软件也在进行提速优化,使用了好多方法,自己管理内存(减少malloc的调用次数),使用HashTable存放经常要进行查找的数据。。。。等等,看到自己开发的软件在速度上有了质的飞跃,实在是很有成就感啊。


  • 上一篇教程: ShadowStarCodeFast截图
  • 下一篇教程: delphi调用sql-server2000存储过程
  •  

    关于本站 | 广告联系 | 版权声明 | 使用帮助

    Copyright © 2004-2008 www.egunao.com All rights reserved.