TFileStream一块一块地读取大文件

时间:2013-11-21 19:43:11

标签: delphi

今天早些时候我在这里打开一个问题,询问我在计算机中扫描文件的方法是否正确。作为解决方案,我收到了一些提示,并且我认为其中一个解决方案:“这需要紧急解决!”,一旦我在内存中完全读取文件,就说内存溢出。所以我开始尝试找到一种方法来逐个读取文件,我得到了一些东西(错误/伪造),我需要一些帮助来弄清楚如何正确地做到这一点。 这个方法现在很简单:

procedure ScanFile(FileName: string);
const
  MAX_SIZE = 100*1024*1024;
var
  i, aux, ReadLimit: integer;
  MyFile: TFileStream;
  Target: AnsiString;
  PlainText: String;
  Buff: array of byte;
  TotalSize: Int64;
begin
  if (POS('.exe', FileName) = 0) and (POS('.dll', FileName) = 0) and
      (POS('.sys', FileName) = 0) then //yeah I know it's not the best way...
    begin
      try
        MyFile:= TFileStream.Create(FileName, fmOpenRead);
      except on E: EFOpenError do
        MyFile:= NIL;
      end;
      if MyFile <> NIL then
      try
        TotalSize:= MyFile.Size;
        while TotalSize > 0 do begin
          ReadLimit:= Min(TotalSize, MAX_SIZE);
          SetLength(Buff, ReadLimit);
          MyFile.ReadBuffer(Buff[0], ReadLimit);
          PlainText:= RemoveNulls(Buff); //this is to transform the array of bytes in string, I posted the code below too...
          for i:= 1 to Length(PlainText) do
            begin //Begin the search..
            end;
          dec(TotalSize, ReadLimit);
         end;
  finally
    MyFile.Free;
  end;
end;

RemoveNulls的代码是:

function RemoveNulls(const Buff: array of byte): String;
var
  i: integer;
begin
  for i:= 0 to Length(Buff) do
    begin
      if Buff[i] <> 0 then
        Result:= Result + Chr(Ord(Buff[i]));
    end;
end;

好的,到目前为止我用这段代码得到的问题是:

1-每次重复一次,我得到更多的内存消耗,当我期望MAX_SIZE变量中描述的只有MAX 100MB时,对吗?

2-我创建了一个文件,其中包含2次应该过滤的内容,由于某些未知原因,我有大约10次重复出现,看起来我正在重复扫描文件。

我感谢你的帮助,如果有人已经完成了这种代码,请在这里发帖,我不假装重新制作轮子......

1 个答案:

答案 0 :(得分:4)

我会说RemoveNulls是你的问题。假设您只是将100MB读入您传递给RemoveNulls的字符串中。然后你将分配一个长度为1的字符串。重新分配到长度2.然后到长度3.然后到长度4.依此类推,一直到100 * 1024 * 1024的长度。

这个过程会破坏你的记忆,而且速度会非常慢。当性能很重要时,应避免堆分配。你根本不需要它。读取文件的一部分,直接在您阅读的缓冲区中搜索。

我可以看到您的代码存在各种问题:

  1. 您的文件扩展名检查已中断,正如我在上一个问题中所述。
  2. 您没有正确处理异常,正如我在上一个问题中所述。
  3. RemoveNulls中的for循环有缓冲区溢出。从low()循环到high()。
  4. 无法评论搜索代码,因为问题中没有。