我在使用TFileStream從文件讀取數據塊到動態數組的一些Delphi代碼時遇到了問題。編寫代碼的最初目的是比較具有相同大小但可能不同日期和時間戳的兩個文件的內容,以查看內容是否相同。這是通過將每對文件中的數據讀入單獨的動態數組並將一個數組的每個字節與另一個數組的相應字節進行比較來完成的。delphi TFileStream「內存不足」
該代碼對TFileStream.Read進行多次調用。大約75次調用後,程序崩潰,出現「內存不足」錯誤消息。
似乎並不重要的是讀取的數據塊有多大,它似乎是導致錯誤消息的調用次數。
該代碼是我編寫的函數,在程序遇到兩個需要比較的文件時調用其他地方(這是由於我不會介紹的原因,可能是四十或五十個不同的文件對) 。無論是以小塊讀取的單個文件,還是整個讀取的多個文件,都會發生「內存不足」錯誤。它似乎是錯誤決定因素的調用次數。
雖然我意識到可能有比下面顯示的文件比較更優雅的方式,但我真正想知道的是使用TFileStream和/或SetLength調用時出了什麼問題這是造成內存問題。每次調用之後,我都試圖釋放內存(如代碼所示),這似乎沒有任何區別。
如果有人能解釋發生了什麼問題,我將不勝感激。
function Compare_file_contents(SPN,TPN : String; SourceFileSize : int64) : boolean;
var
SF : TFileStream; //First file of pair for comparison
TF : TFileStream; //Second file of pair
SourceArray : TBytes; // Buffer array to receive first file data
TargetArray : TBytes; //Buffer array to receive second file data
ArrayLength : int64; //Length of dynamic array
Position : int64; //Position within files to start each block of data read
TestPosition : int64; //Position within dynamic arrays to compare each byte
MaxArrayLength : integer; //Maximum size for the buffer arrays
LastRun : Boolean; //End first repeat loop
begin
{ The comparison has an arbitrary upper boundary of 100 MB to avoid slowing the
the overall program. The main files bigger than this will be *.pst files that
will most likely have new dates every time the program is run, so it will take
about the same time to copy the files as it does to read and compare them, and
it will have to be done every time.
The function terminates when it is confirmed that the files are not the same.
If the source file is bigger than 100 MB, it is simply assumed that they are
not identical, thus Result = False. Also, LongInt integers (=integers) have
a range of -2147483648..2147483647, so files bigger than 2 GB will have
overflowed to a negative number. Hence the check to see if the file size is
less than zero.
The outer repeat ... until loop terminates on LastRun, but LastRun should only
be set if SecondLastRun is True, because it will skip the final comparisons in
the inner repeat ... until loop otherwise. }
Result := True;
LastRun := False;
MaxArrayLength := 1024*1024;
if (SourceFileSize > 100*1024*1024) or (SourceFileSize < 0) then Result := False
else
begin
{ The comparison is done by using TFileStream to open and read the data from
the source and target files as bytes to dynamic arrays (TBytes). Then a repeat
loop is used to compare individual bytes until a difference is found or all
of the information has been compared. If a difference is found, Result is
set to False. }
if SourceFileSize > MaxArrayLength then ArrayLength := MaxArrayLength
else ArrayLength := SourceFileSize;
SF := TFileStream.Create(SPN,fmOpenRead);
TF := TFileStream.Create(TPN,fmOpenRead);
Position := 0;
SetLength(SourceArray,ArrayLength);
SetLength(TargetArray,ArrayLength);
try
SF.Read(SourceArray,ArrayLength);
TF.Read(TargetArray,ArrayLength);
Position := SF.Position;
finally
SF.Free;
TF.Free;
end;
repeat
TestPosition := 0;
repeat
if SourceArray[TestPosition] <> TargetArray[TestPosition] then
Result := False;
Inc(TestPosition);
until (Result = False) or (TestPosition = ArrayLength);
if SourceFileSize > Position then
begin
if SourceFileSize - Position - MaxArrayLength > 0 then
ArrayLength := MaxArrayLength
else ArrayLength := SourceFileSize - Position;
SF := TFileStream.Create(SPN,fmOpenRead);
TF := TFileStream.Create(TPN,fmOpenRead);
SF.Position := Position;
TF.Position := Position;
try
SF.Read(SourceArray,ArrayLength);
TF.Read(TargetArray,ArrayLength);
Position := SF.Position;
finally
SF.Free;
TF.Free;
end;
end else LastRun := True;
until (Result = False) or LastRun;
Finalize(SourceArray);
Finalize(TargetArray);
end;
end; { Compare_file_contents }
你能指定你的Delphi版本嗎? – 2013-02-10 20:43:38
對不起,這是XE3。謝謝,克里斯。 – user2058600 2013-02-10 23:17:23