zoukankan      html  css  js  c++  java
  • 对TMemoryStream的一些改进(用到了LockFile)

    对TMemoryStream的一些改进

    怎么又是关于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存放经常要进行查找的数据。。。。等等,看到自己开发的软件在速度上有了质的飞跃,实在是很有成就感啊。

    http://blog.csdn.net/iseekcode/article/details/4906157

  • 相关阅读:
    LeetCode——Generate Parentheses
    LeetCode——Best Time to Buy and Sell Stock IV
    LeetCode——Best Time to Buy and Sell Stock III
    LeetCode——Best Time to Buy and Sell Stock
    LeetCode——Find Minimum in Rotated Sorted Array
    Mahout实现基于用户的协同过滤算法
    使用Java对文件进行解压缩
    LeetCode——Convert Sorted Array to Binary Search Tree
    LeetCode——Missing Number
    LeetCode——Integer to Roman
  • 原文地址:https://www.cnblogs.com/findumars/p/5288432.html
Copyright © 2011-2022 走看看