TFileStream을 사용하여 파일에서 동적 배열로 데이터 청크를 읽는 일부 Delphi 코드에 문제가 있습니다. 코드 작성의 원래 목적은 내용이 동일한 지 확인하기 위해 크기는 같지만 날짜 및 시간 스탬프가 다를 수있는 두 파일의 내용을 비교하는 것입니다. 이것은 쌍의 각 파일에서 별도의 동적 배열로 데이터를 읽고 한 배열의 각 바이트를 다른 바이트의 해당 바이트와 비교하여 수행됩니다.delphi TFileStream "out of memory"
코드는 TFileStream.Read를 여러 번 호출합니다. 약 75 번 통화 후 '메모리 부족'오류 메시지와 함께 프로그램이 중단됩니다.
읽는 데이터 블록의 크기가 얼마나 클지는 모르지만 오류 메시지가 나타나는 호출 수 인 것 같습니다.
코드는 필자가 비교할 필요가있는 두 개의 파일을 발견 할 때마다 필자가 작성한 함수입니다 (필자가 들어 가지 않는 이유 때문에 40 개 또는 50 개의 다른 파일 쌍이 될 수 있음) . '메모리 부족'오류는 작은 블록으로 읽히는 단일 파일이든 전체 전체에서 읽히는 여러 파일이든 상관없이 발생합니다. 그것은 오류의 결정자 인 호출 수 인 것 같습니다.
아래에 표시된 것보다 파일을 비교할 때보다 우아한 방법이 있다는 것을 알고 있지만 실제로 알고 싶은 것은 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 }
델파이 버전을 지정해 주시겠습니까? –
죄송합니다, XE3입니다. 고마워, 크리스. – user2058600