Einzelnen Beitrag anzeigen

Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#55

Re: Eindeutiger Vergleich für große Dateien gesucht

  Alt 3. Aug 2005, 14:26
Delphi-Quellcode:
 P1 := MapViewOfFile(MMF1.fFileMap, FILE_MAP_READ, CurPos, CurPos + AllocGran, AllocGran);
 P2 := MapViewOfFile(MMF2.fFileMap, FILE_MAP_READ, CurPos, CurPos + AllocGran, AllocGran);
 if not CompareMem(P1, P2, AllocGran) then Exit;
 Inc(CurPos, AllocGran);
Ich sehe zwei Fehler

1.) MapViewOfFile() erwartet den Dateioffset der gemappt werden soll als 2x DWord. Du musst also CurPos als Int64 in zwei DWords zerlegen

2.) MapViewOfFile() kann fehlschlagen und dann ist P1 und/oder P2 = nil !

Nun, da du CurPos in MapViewOfFile() FALSCH übergibst ist sogar P1 und P2 = nil und daher deine AV.
Richtiger so


Delphi-Quellcode:
var
  CurPosHi,CurPosLo: DWord;
  CurSize: DWord;
  CurPos: Int64;
  FileHandle1, FileHandle2: THandle;
  MapHandle1, MapHandle2: THandle;
  FileSize: Int64;
begin
  Result := False;
  FileHandle1 := CreateFile(..., FileName1, ...);
  if FileHandle1 <> INVALID_HANDLE_VALUE then
  try
    FileHandle2 := CreateFile(..., FileName2, ...);
    if FileHandle2 <> INVALID_HANDLE_VALUE then
    try
      FileSize := GetFileSizeInt64(FileHandle1);
      if FileSize = GetFileSizeInt64(FileHandle1) then
      begin
        Result := True;
        if FileSize1 > 0 then
        begin
          MapHandle1 := CraeteFileMapping(FileHandle1);
          if MapHandle1 <> INVALID_HANDLE_VALUE then
          try
            MapHandle2 := CreateFileMapping(FileHandle2);
            if MapHandle2 <> INVALID_HANDLE_VALUE then
            try
              CurSize := FileSize mod AllocGran;
              if CurSize = 0 then CurSize := AllocGran;
              CurPos := FileSize - CurSize;
              repeat
                CurPosHi := CurPos div 2^32;
                CurPosLo := CurPos mod 2^32;
                P1 := MapViewOfFile(MapHandle1, ..., CurPosHi, CurPosLo, CurSize);
                if P1 <> nil then
                try
                  P2 := MapViewOfFile(MapHandle2, ..., CurPosHi, CurPosLo, CurSize);
                  if P2 <> nil then
                  try
                    Result := CompareMem(P1, P2, CurSize);
                  finally
                    UnmapViewOfFile(P2);
                  end else RaiseLastWin32Error;
                finally
                  UnmapViewOfFile(P1);
                end else RaiseLastWin32Error;
                CurPos := CurPos - CurSize;
                CurSize := AllocGran;
              until (CurPos < 0) or not Result;
            finally
              CloseFileMapping(MapHandle2);
            end else RaiseLastWin32Error;
          finally
            CloseFileMapping(MapHandle1);
          end else RaiseLastWin32Error;
        end;
      end;
    finally
      CloseFile(FileHandle2);
    end else RaiseLastWin32Error;
  finally
    CloseFile(FileHand1e1);
  end else RaiseLastWin32Error;
end;
Eventuelle Fehler in obigen Pseudocode darfst du behalten

Die Idee das Filemapping erst wirklich in der Vergleichs-Operation zu erzeugen halte ich für absolut richtig. Das wäre mein nächster Vorschlag gewesen. Alledings hätte ich sogar noch das CreateFileMapping() mit in die Vergleichsfunktion integriert.

Gruß hagen

Edit: shit nun zum 3. mal eine Änderung.
Code arbeitet die Datei nun von Hinten nach Vorne ab, da die Wahrscheinlichkeit das sich de dateien am Ende unterscheiden höher sein dürfte. Das Exit/Break wurde entfernt, so ist es sauberer. Try Finallys niemals vergessen !!
  Mit Zitat antworten Zitat