Prüfen, ob zwei Dateien gleich sind
Folgende Funktion prüft, ob zwei Dateien identisch sind. Als Parameter müssen dieser Funktion die kompletten Dateinamen der zu vergleichenden Dateien übergeben werden. Sie werden dann in einen Stream geladen und per CompareMem verglichen. CompareMem eigent sich sehr gut dazu, Speicherbereiche zu vergleichen. So können beliebige Daten in Streams verglichen werden. Weitere Informationen finden Sie in der OnlineHilfe unter dem Stichwort „CompareMem (Funktion)“.
function AreFilesEqual(const file1, file2: string): Boolean; var m1, m2: TMemoryStream; begin Result := False; m1 := nil; m2 := nil; try m1 := TMemoryStream.Create; m2 := TMemoryStream.Create; m1.LoadFromFile(file1); m2.LoadFromFile(file2); if m1.Size = m2.Size then Result := CompareMem(m1.Memory, m2.Memory, m1.Size); finally m1.Free; m2.Free; end end;
Da die Lösung für große Dateien sehr speicherfressend ist, lädt folgende Funktion immer nur einen Teil in einen internen Puffer und vergleicht diesen. Der Funktion müssen zwei Streams übergeben werden. Sie gibt True zurück, fall die Streams einen identischen Inhalt besitzen:
function CompareStreams(A,B: TStream):Boolean; const cMaxBuffer = 1024*256; var OldPosA, OldPosB: Int64; nRead: Integer; BufferA, BufferB: array[0..cMaxBuffer-1] of Byte; CurPos: Int64; Size: Int64; begin Result := False; if A.Size B.Size then Exit; OldPosA := A.Position; OldPosB := B.Position; try A.Seek(0, soFromBeginning); B.Seek(0, soFromBeginning); Size := A.Size; CurPos := 0; nRead := cMaxBuffer; while(CurPos Size-cMaxBuffer then nRead := Size-CurPos; A.Read(BufferA, nRead); B.Read(BufferB, nRead); if not CompareMem(@BufferA, @BufferB, nRead) then Exit; Inc(CurPos, nRead); end; Result := True; finally A.Seek(OldPosA, soFromBeginning); B.Seek(OldPosB, soFromBeginning); end; end;
Aufgerufen werden kann die Funktion beispielsweise so:
procedure TForm1.Button1Click(Sender: TObject); var FileA, FileB: TFileStream; begin FileA := nil; FileB := nil; try FileA := TFileStream.Create('c:filea.bin', fmOpenRead or fmShareDenyWrite); FileB := TFileStream.Create('c:fileb.bin', fmOpenRead or fmShareDenyWrite); try if not CompareStreams(FileA, FileB) then ShowMessage('Dateien sind ungleich') else ShowMessage('Dateien sind gleich :-)'); except ShowMessage('Es ist ein Fehler beim vergleichen der Streams aufgetreten.'); end; finally FileA.Free; FileB.Free; end; end;