今天早些时候我在这里打开一个问题,询问我在计算机中扫描文件的方法是否正确。作为解决方案,我收到了一些提示,并且我认为其中一个解决方案:“这需要紧急解决!”,一旦我在内存中完全读取文件,就说内存溢出。所以我开始尝试找到一种方法来逐个读取文件,我得到了一些东西(错误/伪造),我需要一些帮助来弄清楚如何正确地做到这一点。 这个方法现在很简单:
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次重复出现,看起来我正在重复扫描文件。
我感谢你的帮助,如果有人已经完成了这种代码,请在这里发帖,我不假装重新制作轮子......
答案 0 :(得分:4)
我会说RemoveNulls是你的问题。假设您只是将100MB读入您传递给RemoveNulls的字符串中。然后你将分配一个长度为1的字符串。重新分配到长度2.然后到长度3.然后到长度4.依此类推,一直到100 * 1024 * 1024的长度。
这个过程会破坏你的记忆,而且速度会非常慢。当性能很重要时,应避免堆分配。你根本不需要它。读取文件的一部分,直接在您阅读的缓冲区中搜索。
我可以看到您的代码存在各种问题:
无法评论搜索代码,因为问题中没有。