function GetFileSizeInt64(
const FileName:
String): Int64;
var
Handle: THandle;
Data: WIN32_FIND_DATA;
begin
Result := -1;
Handle := FindFirstFile(Pointer(FileName), Data);
if Handle <> INVALID_HANDLE_VALUE
then
try
Int64Rec(Result).Hi := Data.nFileSizeHigh;
Int64Rec(Result).Lo := Data.nFileSizeLow;
finally
Windows.FindClose(
Handle);
end;
end;
function GetSystemAllocationGranularity: DWord;
var
Info: TSystemInfo;
begin
GetSystemInfo(Info);
Result := Info.dwAllocationGranularity;
end;
function CompareFile(
const FileName1, FileName2:
String): Boolean;
procedure DoError;
begin
RaiseLastWin32Error;
// auskommentieren falls keine Exceptions erwünscht
// Result := False;
end;
var
AllocSize: DWord;
CurSize: DWord;
CurPos: Int64;
FileHandle1, FileHandle2: THandle;
MapHandle1, MapHandle2: THandle;
FileSize1, FileSize2: Int64;
View1, View2: Pointer;
begin
Result := AnsiCompareText(FileName1, FileName2) = 0;
if Result
then Exit;
FileSize1 := GetFileSizeInt64(FileName1);
FileSize2 := GetFileSizeInt64(FileName2);
if FileSize1
or FileSize2 >= 0
then
begin
Result := FileSize1 = FileSize2;
if not Result
or (FileSize1 = 0)
then Exit;
AllocSize := GetSystemAllocationGranularity * 8;
Assert(AllocSize < MaxInt);
// CompareMem() Size Param is Integer
FileHandle1 := CreateFile(Pointer(FileName1), GENERIC_READ, FILE_SHARE_READ,
nil, OPEN_EXISTING, 0, 0);
if FileHandle1 <> INVALID_HANDLE_VALUE
then
try
FileHandle2 := CreateFile(Pointer(FileName2), GENERIC_READ, FILE_SHARE_READ,
nil, OPEN_EXISTING, 0, 0);
if FileHandle2 <> INVALID_HANDLE_VALUE
then
try
MapHandle1 := CreateFileMapping(FileHandle1,
nil, PAGE_READONLY, 0, 0,
nil);
if MapHandle1 <> INVALID_HANDLE_VALUE
then
try
MapHandle2 := CreateFileMapping(FileHandle2,
nil, PAGE_READONLY, 0, 0,
nil);
if MapHandle2 <> INVALID_HANDLE_VALUE
then
try
CurSize := FileSize1
mod AllocSize;
if CurSize = 0
then CurSize := AllocSize;
CurPos := FileSize1 - CurSize;
repeat
Assert(CurPos >= 0);
Assert(CurPos
mod AllocSize = 0);
View1 := MapViewOfFile(MapHandle1, FILE_MAP_READ, Int64Rec(CurPos).Hi, Int64Rec(CurPos).Lo, CurSize);
if View1 <>
nil then
try
View2 := MapViewOfFile(MapHandle2, FILE_MAP_READ, Int64Rec(CurPos).Hi, Int64Rec(CurPos).Lo, CurSize);
if View2 <>
nil then
try
Result := CompareMem(View1, View2, CurSize);
finally
UnmapViewOfFile(View2);
end else DoError;
finally
UnmapViewOfFile(View1);
end else DoError;
CurSize := AllocSize;
// 1.)
CurPos := CurPos - CurSize;
// 2.)
until not Result
or (CurPos < 0);
finally
CloseHandle(MapHandle2);
end else DoError;
finally
CloseHandle(MapHandle1);
end else DoError;
finally
CloseHandle(FileHandle2);
end else DoError;
finally
CloseHandle(FileHandle1);
end else DoError;
end else DoError;
end;
function CompareFile1(
const FileName1, FileName2:
String): Boolean;
procedure DoError;
begin
RaiseLastWin32Error;
// Result := False;
end;
const
BufferSize = 65535;
var
FileSize1,FileSize2: Int64;
CurSize: Integer;
Stream1,Stream2: TStream;
Buffer1,Buffer2:
array of Byte;
begin
Result := AnsiCompareText(FileName1, FileName2) = 0;
if Result
then Exit;
FileSize1 := GetFileSizeInt64(FileName1);
FileSize2 := GetFileSizeInt64(FileName2);
if FileSize1
or FileSize2 >=0
then
begin
Result := FileSize1 = FileSize2;
if not Result
or (FileSize1 = 0)
then Exit;
Stream1 := TFileStream.Create(FileName1, fmOpenRead
or fmShareDenyWrite);
try
Stream2 := TFileStream.Create(FileName2, fmOpenRead
or fmShareDenyWrite);
try
SetLength(Buffer1, BufferSize);
SetLength(Buffer2, BufferSize);
while Result
and (FileSize1 > 0)
do
begin
CurSize := BufferSize;
if CurSize > FileSize1
then CurSize := FileSize1;
Stream1.
Read(Buffer1[0], CurSize);
Stream2.
Read(Buffer2[0], CurSize);
Result := CompareMem(@Buffer1[0], @Buffer2[0], CurSize);
FileSize1 := FileSize1 - CurSize;
end;
finally
Stream2.Free;
end;
finally
Stream1.Free;
end;
end else DoError;
end;