一个读取速度超快的FileStream

时间:2010-01-26 14:50:34  来源:第二电脑网  作者:第二电脑网

  第二电脑网导读:组件必须接受一整个 TStream,作为其存储媒介,整个过程简直慢得无法忍受。   之所以速度慢,是有两方面的原因:1。用TFileStream打开文件,操作系统在打开文件后会为文件生成内存镜像,文件一大,那么开辟空间以及内存拷贝的工作就会变得极为缓慢。2。将TFileStream中的一部分再复制给TMemoryStream,这个复制过程会开辟新的内存再进行复制,理所当然...
  正文:

最近一直为自己制作的相册软件打开大文件时速度慢而郁闷,我以前的做法是先用TFileStream打开一个文件,然后在其中找到其中的数据段,把其中内容复制给一个 TMemoryStream,之所以要再将它复制给一个独立的TMemoryStream是因为,后续处理的一个文件型数据库组件必须接受一整个 TStream,作为其存储媒介,整个过程简直慢得无法忍受。

   之所以速度慢,是有两方面的原因:
1。用TFileStream打开文件,操作系统在打开文件后会为文件生成内存镜像,文件一大,那么开辟空间以及内存拷贝的工作就会变得极为缓慢。
2。将TFileStream中的一部分再复制给TMemoryStream,这个复制过程会开辟新的内存再进行复制,理所当然内存大了,复制时间也会变长。

   我决心针对目前我所遇到的问题,再写一个文件读取类,目前就叫TFastFileStream吧,它必须从TStream继承而来,这样才能和其它组件方便地结合起来。

   首先,要解决的是打开大文件慢的问题,对于这个,使用MapViewOfFile(),将文件直接当作内存镜像来访问就可以了,关于 MapViewOfFile(),以及文件内存镜像,可以参考这篇文章:http://www.vccode.com/file_show.PHP?id =2409

Delphi下建立文件镜像的方法为:


constructor TFastFileStream.Create(const AFileName:String);
var
FileSizeHigh:Longword;
begin
  FFileHandle:=CreateFile(PChar(AFileName),GENERIC_READ,FILE_SHARE_READ,nil,OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,0);
  if FFileHandle=INVALID_HANDLE_VALUE then begin
    raise FastFileStreamException.Create('Error when open file');
  end;
  FSize:=GetFileSize(FFileHandle,@FileSizeHigh);
  if FSize=INVALID_FILE_SIZE then begin
    raise FastFileStreamException.Create('Error when get file size');
  end;
  FMappingHandle:=CreateFileMapping(FFileHandle,nil,PAGE_READONLY,0,0,nil);
  if FMappingHandle=0 then begin
    raise FastFileStreamException.Create('Error when mapping file');
  end;
  FMemory:=MapViewOfFile(FMappingHandle,FILE_MAP_READ,0,0,0);
  if FMemory=nil then begin
    raise FastFileStreamException.Create('Error when map view of file');
  end;
end;

最后,被做成镜像的数据就存放在FMemory中了,然后,覆盖TStream的Read()方法,当外部需要取得数据时,让它到FMemory中去取:


function TFastFileStream.Read(var Buffer;Count:LongInt):LongInt;
begin
  if (FPosition >= 0) and (Count >= 0) then
  begin
    Result := FSize - FPosition;
    if Result > 0 then
    begin
      if Result > Count then Result := Count;
      //Move(Pointer(Longint(FMemory) + FPosition)^, Buffer, Result);
CopyMemory(Pointer(@Buffer),Pointer(LongInt(FMemory)+FPosition),Result);
      Inc(FPosition, Result);
      Exit;
    end;
  end;
  Result := 0;
end;

这段函数主要还是模仿TCustomMemoryStream中的同名方法来写的,但是有一点比较奇怪,当我使用Delphi自己的内存拷贝函数Move()时,程序总是会访问到非法地址,所以只好改为用API函数CopyMemory()了。

另外,需要实现的函数还有:


function TFastFileStream.GetSize():Int64;
begin
  result:=FSize;
end;
一个读取速度超快的FileStream》由第二电脑网原创提供,转载请注明:http://www.002pc.com/master/College/Language/Delphi/2010-01-26/12444.html


关键字:

关于《一个读取速度超快的FileStream》文章的评论

站内搜索: 高级搜索

热门搜索: Windows style 系统 tr IP QQ CPU 安装 function 注册 if td