Home » Tipps & Tricks » Dateien/Verzeichnisse » Dateioperationen » Prüfen, ob zwei Dateien gleich sind

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;