AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Sonstige Fragen zu Delphi Delphi Eindeutiger Vergleich für große Dateien gesucht
Thema durchsuchen
Ansicht
Themen-Optionen

Eindeutiger Vergleich für große Dateien gesucht

Ein Thema von dahead · begonnen am 2. Aug 2005 · letzter Beitrag vom 10. Mai 2014
Antwort Antwort
Seite 7 von 12   « Erste     567 89     Letzte »    
Benutzerbild von dahead
dahead

Registriert seit: 16. Mai 2005
620 Beiträge
 
#61

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

  Alt 3. Aug 2005, 17:31
@supermuckl:

mit was willst du vergleichen? mit TFileStream?
  Mit Zitat antworten Zitat
supermuckl

Registriert seit: 1. Feb 2003
1.340 Beiträge
 
FreePascal / Lazarus
 
#62

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

  Alt 3. Aug 2005, 17:58
jep
Das echte Leben ist was für Leute...
... die im Internet keine Freunde finden!
  Mit Zitat antworten Zitat
Benutzerbild von dahead
dahead

Registriert seit: 16. Mai 2005
620 Beiträge
 
#63

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

  Alt 3. Aug 2005, 18:16
ok, hier ist der vergleich. ich weise aber darauf hin, dass die prozedur CompareFilesFileStream die daten von vorne nach hinten liest, während CompareFilesMemoryMapped von hinten nach vorne (s. negaH's post). das heisst die prozedur CompareFilesFileStream müsste dahingehend optimiert werden um einen einigermaßen adequaten vergleich zu erzielen.

zum vergleich:
daten die überprüft wurden: 22 dateien, gesamtgröße: 6.480.244.455 Bytes. dabei war die datei, auf die es ankommt (wwdofficialnltls7l1.exe, 1.438.201.380 Bytes) zweifach vorhanden, um zu testen ob sie als unterschiedlich oder gleich erkannt wird.

hier der verwendete code:

Delphi-Quellcode:
function CompareFilesFileStream(const File1, File2: String): Boolean;
const
  BlockSize = 65536;
var
  FSFile1, FSFile2: TFileStream;
  L1, L2: Integer;
  B1, B2: Array[1..BlockSize] of Byte;
begin
  Result := False;
  FSFile1 := TFileStream.Create(File1, fmOpenRead or fmShareDenyWrite);
  try
    FSFile2 := TFileStream.Create(File2, fmOpenRead or fmShareDenyWrite);
    try
      if FSFile1.Size = FSFile2.Size then
      begin
        while FSFile1.Position < FSFile1.Size do
        begin
          L1 := FSFile1.Read(B1[1], BlockSize);
          L2 := FSFile2.Read(B2[1], BlockSize);
          if L1 <> L2 then
            Exit;
          if not CompareMem(@B1[1], @B2[1], L1) then
           Exit;
        end;
        Result := True;
      end;
    finally
      FSFile2.Free;
    end;
  finally
    FSFile1.Free;
  end;
end;
Quelle

und hier die prozedur die mittlerweile entstanden ist.

Delphi-Quellcode:
function GetHugeFileSize(const Filename: String): Int64;
var
  hFile: Longword;
  Data: WIN32_FIND_DATA;
  Size: LARGE_INTEGER;
begin
  Result := -1;
  hFile := FindFirstFile(PChar(Filename), Data);
  try
   if hFile <> INVALID_HANDLE_VALUE then
    begin
     Size.LowPart := Data.nFileSizeLow;
     Size.HighPart := Data.nFileSizeHigh;
     Result := Size.QuadPart;
   end;
  finally
   Windows.FindClose(hFile);
  end;
end;

function GetSystemAllocationGranularity: Cardinal;
var
  PSysInfo: TSystemInfo;
begin
  GetSystemInfo(PSysInfo);
  Result := PSysInfo.dwAllocationGranularity;
end;

function CompareFilesMemoryMapped(const File1, File2: String; SysAllocSize: Cardinal): Boolean;
var
  CurSize: DWord;
  CurPos: Int64;
  hFile1, hFile2: THandle;
  hMap1, hMap2: THandle;
  FileSize: Int64;
  P1, P2: Pointer;
begin
  Result := False;

  hFile1 := CreateFile(@File1[1], GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);

  if hFile1 <> INVALID_HANDLE_VALUE then
  try
   hFile2 := CreateFile(@File2[1], GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
   if hFile2 <> INVALID_HANDLE_VALUE then
    try
      FileSize := GetHugeFileSize(File1); //GetFileSizeInt64(hFile1);
      if FileSize = GetHugeFileSize(File2) then //GetFileSizeInt64(hFile1) then
      begin
        Result := True;
        if FileSize > 0 then
        begin
          hMap1 := CreateFileMapping(hFile1, nil, PAGE_READONLY, 0, 0, nil);
          if hMap1 <> INVALID_HANDLE_VALUE then
          try
            hMap2 := CreateFileMapping(hFile2, nil, PAGE_READONLY, 0, 0, nil);
            if hMap2 <> INVALID_HANDLE_VALUE then
            try
              CurSize := FileSize mod SysAllocSize;
              if CurSize = 0 then
               CurSize := SysAllocSize;
              CurPos := FileSize - CurSize;
              repeat
               P1 := MapViewOfFile(hMap1, FILE_MAP_READ, Int64Rec(CurPos).Hi, Int64Rec(CurPos).Lo, CurSize);
                if P1 <> nil then
                try
                 P2 := MapViewOfFile(hMap2, FILE_MAP_READ, Int64Rec(CurPos).Hi, Int64Rec(CurPos).Lo, 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 := SysAllocSize;
              until
               (CurPos <= 0) or (not Result);
            finally
             CloseHandle(hMap2);
            end; // else RaiseLastWin32Error;
          finally
           CloseHandle(hMap1);
          end; // else RaiseLastWin32Error;
        end;
      end;
    finally
     CloseHandle(hFile2);
    end; // else RaiseLastWin32Error;
  finally
   CloseHandle(hFile1);
  end; // else RaiseLastWin32Error;
end;
ich hoffe, dass soweit alles fehlerfrei ist. am besten wäre natürlich, wenn du beide prozeduren selbst mal testest und mir eventuelle fehler nennst.

hinweis: ich habe während der beiden vergleiche noch andere programme/dienste laufen usw. d. h. die vergleiche sind nicht sonderlich aussagekräftig, aber ich denke das ergebnis spricht für sich (wie gesagt, falls alles richtig ist).

das maßgebliche an den screenshots ist die zeit (statusbar rechts unten).
Miniaturansicht angehängter Grafiken
tfilestream_316.jpg   tmemorymappedfile_973.jpg  
  Mit Zitat antworten Zitat
Benutzerbild von Flocke
Flocke

Registriert seit: 9. Jun 2005
Ort: Unna
1.172 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#64

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

  Alt 3. Aug 2005, 18:21
Ich will mal nicht unken, aber 0,20 Sekunden KANN NICHT SEIN, bei keiner Festplatte der Welt!

[Nachtrag]

Modifizier die Routine mal so (rote Stellen), dann bekommst du mit, ob ein Fehler aufgetreten ist (was ich mir denke):
Code:
function CompareFilesMemoryMapped(const File1, File2: String; SysAllocSize: Cardinal): [color=red]integer[/color];
var
  CurSize: DWord;
  CurPos: Int64;
  hFile1, hFile2: THandle;
  hMap1, hMap2: THandle;
  FileSize: Int64;
  P1, P2: Pointer;
begin
  [color=red]Result := -1;[/color]

  hFile1 := CreateFile(@File1[1], GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);

  if hFile1 <> INVALID_HANDLE_VALUE then
  try
   hFile2 := CreateFile(@File2[1], GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
   if hFile2 <> INVALID_HANDLE_VALUE then
    try
      FileSize := GetHugeFileSize(File1); //GetFileSizeInt64(hFile1);
      if FileSize = GetHugeFileSize(File2) then //GetFileSizeInt64(hFile1) then
      begin
        Result := True;
        if FileSize > 0 then
        begin
          hMap1 := CreateFileMapping(hFile1, nil, PAGE_READONLY, 0, 0, nil);
          if hMap1 <> INVALID_HANDLE_VALUE then
          try
            hMap2 := CreateFileMapping(hFile2, nil, PAGE_READONLY, 0, 0, nil);
            if hMap2 <> INVALID_HANDLE_VALUE then
            try
              CurSize := FileSize mod SysAllocSize;
              if CurSize = 0 then
               CurSize := SysAllocSize;
              CurPos := FileSize - CurSize;
              repeat
               P1 := MapViewOfFile(hMap1, FILE_MAP_READ, Int64Rec(CurPos).Hi, Int64Rec(CurPos).Lo, CurSize);
                if P1 <> nil then
                try
                 P2 := MapViewOfFile(hMap2, FILE_MAP_READ, Int64Rec(CurPos).Hi, Int64Rec(CurPos).Lo, CurSize);
                 if P2 <> nil then
                  try
                   [color=red]if CompareMem(P1, P2, CurSize)
                     then Result := 1
                     else Result := 0;[/color]
                  finally
                   UnmapViewOfFile(P2);
                  end; // else RaiseLastWin32Error;
                finally
                  UnmapViewOfFile(P1);
                end; // else RaiseLastWin32Error;
                CurPos := CurPos - CurSize;
                CurSize := SysAllocSize;
              until
               (CurPos <= 0) or (not Result);
            finally
             CloseHandle(hMap2);
            end; // else RaiseLastWin32Error;
          finally
           CloseHandle(hMap1);
          end; // else RaiseLastWin32Error;
        end;
      end;
    finally
     CloseHandle(hFile2);
    end; // else RaiseLastWin32Error;
  finally
   CloseHandle(hFile1);
  end; // else RaiseLastWin32Error;
end;
Volker
  Mit Zitat antworten Zitat
Benutzerbild von dahead
dahead

Registriert seit: 16. Mai 2005
620 Beiträge
 
#65

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

  Alt 3. Aug 2005, 18:42
wie gesagt, es können noch fehler enthalten sein.

ich habe mal das boolean statement durch integer ersetzt und bekomme zwar auch je nach datei mal eine -1 zurück, aber soweit ich das sehe nur deshalb, weil die dateien ungleich sind. doppelte (gleiche/identische) dateien werden richtig bestimmt.

ich gebe dir recht, die benötigte zeit ist absolut erstaunlich, aber selbst mit breakpoints scheint er zumindest bei fragwürdigen dateien alles korrekt auszuführen.

wo könnte der fehler sein?

edit: jetzt habe ich mal negaH's RaiseLastWin32Error wieder aktiviert.

ich bekomme einen "System Error Code 1132: Die angegebene Basisadresse oder Dateioffset ist falsch ausgerichtet."

werde mal überprüfen wie und warum. danke für den hinweis!
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

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

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

  Alt 3. Aug 2005, 18:51
Ziehe mal eine weitere Kopie der doppelten Datei und ändere in dieser Datei möglichst nur 1 Byte exakt in der Mitte der Datei.

Auch ich meine das 0.2 Sekunden enorm schnell ist, einfach zu schnell.

Das Result auf Integer zu setzen ist keine gute Idee und lass doch mal alle RaiseLastWin32Error drinnen. Falls nämlich irgendeine API Funktion fehlschlägt so wird eine Exception auftreten und schwups finden wir den eventuellen Fehler.

Gruß Hagen
  Mit Zitat antworten Zitat
Benutzerbild von dahead
dahead

Registriert seit: 16. Mai 2005
620 Beiträge
 
#67

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

  Alt 3. Aug 2005, 18:55
@negaH:

Zitat:
Falls nämlich irgendeine API Funktion fehlschlägt so wird eine Exception auftreten und schwups finden wir den eventuellen Fehler.
ja, siehe obigen post.

Zitat:
"System Error Code 1132: Die angegebene Basisadresse oder Dateioffset ist falsch ausgerichtet."
edit1:
jetzt weiß ich auch die stelle:

Delphi-Quellcode:
if P2 <> nil then
 try
  Result := CompareMem(P1, P2, CurSize);
 finally
 UnmapViewOfFile(P2);
 end else
 RaiseLastWin32Error; // <- hier kommt die AV
edit2:
http://www.support.softwaretechnolog...ain/R10307.htm
"The base address or the file offset specified does not have the proper alignment." "ERROR_MAPPED_ALIGNMENT"

muss mal kucken wann und weshalb der auftritt.

edit3:

quelle: http://support.microsoft.com/kb/q125713/
Zitat:
For the lpvBase parameter specified in a call to MapViewOfFileEx(), you should use an integral multiple of the system's allocation granularity. On Windows NT, not specifying such a value will cause MapViewOfFileEx() to fail, and GetLastError() to return ERROR_MAPPED_ALIGNMENT (1132). On Windows 95, the address is rounded down to the nearest integral multiple of the system's allocation granularity.
  Mit Zitat antworten Zitat
supermuckl

Registriert seit: 1. Feb 2003
1.340 Beiträge
 
FreePascal / Lazarus
 
#68

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

  Alt 3. Aug 2005, 19:23
ich würde dich auch noch bitten (wenn du die fehler korrigiert hast) auch noch meine methode zu testen, da ich damit mit größeren blöcken arbeite und mach meiner theorie bei großen dateien, dort mehr speed rauskommen KÖNNTE

Delphi-Quellcode:
function SameFile(File1,File2:String):boolean;
var
s1,s2:Tfilestream;
block:int64;
buffer1,buffer2: string;
begin
result := false;
try
s1 := Tfilestream.Create(File1,fmOpenRead);
s2 := Tfilestream.Create(File2,fmOpenRead);

if s1.Size <> s2.Size then begin
  result := false;
end else begin
  s1.Position := 0;
  s2.Position := 0;
  block := 10485760; //10MB hier eventuell mal verschiedene werte ausprobieren (1,10,20,30,100)
          if s1.Position+block > s1.Size-1 then
                                  block := s1.Size-s1.Position;
  result := true;
  setlength(buffer1,block);
  setlength(buffer2,block);
  while( s1.Position <> s1.Size ) do begin
        if s1.Position+block > s1.Size-1 then
                                  block := s1.Size-s1.Position;
        s1.Read(buffer1[1],block);
        s2.Read(buffer2[1],block);
        if buffer1 <> buffer2 then begin
        result := false;
        break;
        end;

  end;

end;
finally
s1.Free;
s2.Free;
end;
end;
Das echte Leben ist was für Leute...
... die im Internet keine Freunde finden!
  Mit Zitat antworten Zitat
Benutzerbild von dahead
dahead

Registriert seit: 16. Mai 2005
620 Beiträge
 
#69

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

  Alt 3. Aug 2005, 20:00
den fehler hab ich zwar noch nicht korrigiert, aber vorhin deine methode getestet.

bei gleichem verzeichnis wie oben hat es 715 sek. gedauert.
Miniaturansicht angehängter Grafiken
samefile_211.jpg  
  Mit Zitat antworten Zitat
Benutzerbild von dahead
dahead

Registriert seit: 16. Mai 2005
620 Beiträge
 
#70

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

  Alt 4. Aug 2005, 01:07
@supermuckl: bezüglich der performance (i/o u. mmf) habe ich einen relativ interessanten artikel gefunden:

http://blogs.borland.com/dcc/archive...3/19/2380.aspx
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 7 von 12   « Erste     567 89     Letzte »    


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:03 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz