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 8 von 12   « Erste     678 910     Letzte »    
supermuckl

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

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

  Alt 4. Aug 2005, 01:55
genau den beitrag hatte ich mal vor ner zeit inhaliert. und dann eine große mmf klasse geschrieben.
die allerdings DB like funktioniert und nicht byte für byte
Das echte Leben ist was für Leute...
... die im Internet keine Freunde finden!
  Mit Zitat antworten Zitat
Benutzerbild von FriFra
FriFra

Registriert seit: 19. Apr 2003
1.291 Beiträge
 
Delphi 2005 Professional
 
#72

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

  Alt 4. Aug 2005, 10:59
@negah: Ich hab auch mal versucht Deinen Code umzusetzen... leider kommt es beim Vergleich hin und wieder zu Fehlern...
Delphi-Quellcode:
Result := False;
    FileHandle1 := FileOpen(FileName1, fmOpenRead or fmShareDenyWrite);
    if FileHandle1 <> INVALID_HANDLE_VALUE then
    try
      FileHandle2 := FileOpen(FileName2, fmOpenRead or fmShareDenyWrite);
      if FileHandle2 <> INVALID_HANDLE_VALUE then
      try
        FileSize := GetFileSize(FileHandle1, nil);
        if FileSize = GetFileSize(FileHandle2, nil) then
        begin
          Result := True;
          if FileSize > 0 then
          begin
            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 := FileSize mod AllocGran;
                if CurSize = 0 then
                  CurSize := AllocGran;
                CurPos := FileSize - CurSize;
                repeat
                  CurPosHi := CurPos div 4294967296;
                  CurPosLo := CurPos mod 4294967296;
                  P1 := MapViewOfFile(MapHandle1, FILE_MAP_READ, CurPosHi,
                    CurPosLo, CurSize);
                  if P1 <> nil then
                  try
                    P2 := MapViewOfFile(MapHandle2, FILE_MAP_READ, 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
                CloseHandle(MapHandle2);
              end
              else
                RaiseLastWin32Error;
            finally
              CloseHandle(MapHandle1);
            end
            else
              RaiseLastWin32Error; // <------------ Hier wird der Fehler angezeigt
                                    // MapHandle1 ist also INVALID_HANDLE_VALUE
                                    // Warum?
          end;
        end;
      finally
        FileClose(FileHandle2);
      end
      else
        RaiseLastWin32Error;
    finally
      FileClose(FileHandle1);
    end
    else
      RaiseLastWin32Error;
Elektronische Bauelemente funktionieren mit Rauch. Kommt der Rauch raus, geht das Bauteil nicht mehr.
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

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

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

  Alt 4. Aug 2005, 11:54
keine Ahnung ?!

hast du mal gecheckt

iff AnsiCompareText(FileName1, FileName2) <> 0 !!!

eventuell kann es also sein das beide oder eine der Dateien schon geöffnet wurde und du keinen Zugriff mit deinem Zugriffsflags bekommst.

fmShareDenyWrite

könnte das Problem sein falls ein anderer Process die Datei mit Vollzugriff oder sogar exklusiv geöffnet hat.
Dann treten Fehler NICHT sofort mit FileOpen(), GetFileSize() etc. pp. auf sondern erst wenn man Daten aus der Datei lesen möchte.

Dieser Fehler kann dir aber mit jeder Methode zu jeder Zeit auftreten, das OS und die anderen Anwendungen möchte halt auch ihre Daten speichern

Gruß Hagen

PS: als Entschuldigung für denMist muß ich auch sagen das der obige Source von mir niemals getestet wurde, nochnichtmal das er auf meinem Rechner jemals das Licht eines Compilers gesehen hätte ich habe ihn hier live programmiert.
  Mit Zitat antworten Zitat
Benutzerbild von FriFra
FriFra

Registriert seit: 19. Apr 2003
1.291 Beiträge
 
Delphi 2005 Professional
 
#74

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

  Alt 4. Aug 2005, 12:19
da hatte ich doch gerade den "falschen" Fehler markiert...
Viel häufiger tritt jedoch an folgender Stelle ein Fehler auf:
Delphi-Quellcode:
P1 := MapViewOfFile(MapHandle1, FILE_MAP_READ, CurPosHi,
                    CurPosLo, CurSize);
...
Zitat von Mein Programm:
Systemfehler. Code: 1132
Die angegebene Basisadresse oder der angegwebene Dateioffset ist falsch ausgerichtet.
Es scheint also CurPosHi und/oder CurPosLo nicht zu passen ...
Elektronische Bauelemente funktionieren mit Rauch. Kommt der Rauch raus, geht das Bauteil nicht mehr.
  Mit Zitat antworten Zitat
Benutzerbild von dahead
dahead

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

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

  Alt 4. Aug 2005, 12:33
@frifra, @negaH:

genau den selben fehler erhalte ich ja auch. ich hab mich schon gewundert warum du einen anderen bekommst.

ich habe gestern noch einiges zu dem thema gelesen, und es muss wohl wirklich an CurPosHi u. CurPosLo liegen. Irgendwie werden die falsch geteilt, bzw. der rest ist nicht mit "dwAllocationGranularity" kompatibel.

ich weiß aber momentan auch nicht wirklich warum.
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

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

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

  Alt 4. Aug 2005, 13:01
Jaja, wenn man einfach stupid irgendwas abtippt das ein Fachidiot ohne eigene Tests gepostet hat

Beachtet bitte die beiden Zeilen die mit 1.) und 2.) makiert wurden.

Delphi-Quellcode:
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;
So. Bei meinen Test ist CompareFile() ca. 140% schneller als CompareFile1().
Aber am wichtigsten dürfter der Fakt sein das CompareFile() umso schneller arbeitet um so öfters eine Datei als MMF in den Speicher geladen wurde, sprich schon im Cache ist. Das ist gut so denn ich nehme an das zumindestens eine der beiden Dateien kurz vorher, ebenfalls per MMF, gehasht wurde. D.h. sie ist schon im Speicher weil man ja noch den Hash per MD4 vorher ziehen wird. Die andere Datei stellt ja die Referenz die schon in der Datenbank gespeichert wurde,also auch deren Hash Wert. Somit dürften die MMF's tatsächlich einiges an Speed bringen.

Gruß Hagen
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

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

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

  Alt 4. Aug 2005, 13:15
Wenn man es aber genauer betrachtet so sind 140% zu wenig falls man mit Hashs arbeiten wird. Die Wahrscheinlichkeit das nach einer MD4 Hash Überprüfung die Funktion CompareFile() aufgerufen werden muß ist einfach viel zu gering um nicht mit den VCL-Streams zu arbeiten, besondersim Hinblick auf die negativen Seiteneffekte der MMF's wie beim Borland Link oben beschrieben. (kannte ich selber noch nicht)
Bei einer MD4 Hash Überprüfung hat man ja zumindestens schonmal einen Hashwert einer der beiden Dateien in einer DB gespeichert. Die Erzeugung der MD4 Prüfsumme für die zweite Datei muß ja nur diese zweite Datei öffnen und laden. Das verringert schonmal um 200% den nötigen Aufwand.

Gruß Hagen
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

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

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

  Alt 4. Aug 2005, 14:09
So nachfolgend noch ein Code um einen MD4 über eine Datei zu ziehen.
Dieses mal sieht die Performance schon anders aus. Es gibt in fact keinen Unterschied mehr zwischen MMF's und normalen Streams, also sollten Streams benutzt werden.
Allerdings unterscheidet sich die Laufzeit zwischen MD4HashFile1() und CompareFile() enorm. Mit meinen 160Mb großen Testdateien, die noch NICHT im Cache lagen, sieht es nun so aus:

CompareFile1() benötigt 55 Sekunden.
HashFile1() benötigt 10 Sekunden.

Was lernen wir daraus ?
Das ein zweimaliger Aufruf von HashFile1() ca. 20 Sekunden benötigt und somit mehr als doppelt so schnell ist wie nur ein Aufruf von CompareFile1() !!

Gruß Hagen

PS: wer's in die CodeLib stellen will soll es selber tuen


Delphi-Quellcode:
type
  PMD4Digest = ^TMD4Digest;
  TMD4Digest = array[0..3] of Cardinal;

  PMD4Buffer = ^TMD4Buffer;
  TMD4Buffer = array[0..15] of Cardinal;
//
// Rest im Anhang des Postings
//
[edit=Sharky]Nach Rücksprache den gesamt Code als Datei angehängt. Mfg, Sharky[/edit]
Angehängte Dateien
Dateityp: zip md4_hashfile_914.zip (2,7 KB, 29x aufgerufen)
  Mit Zitat antworten Zitat
Benutzerbild von dahead
dahead

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

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

  Alt 4. Aug 2005, 14:17
@negaH:

ich habe die korrigierte fassung der comparefile prozedur (also mmf) über das selbe verzeichnis laufen lassen.
ich dachte zwar schon, das programm hätte sich aufgehängt, aber nach 1391 sekunden war er dann doch noch erfolgreich fertig.

jaja, die 0,2 sek. wären auch zu schön um wahr zu sein. trotzdem vielen dank für die mühe u. arbeit die du dir hier gemacht hast.

Zitat:
PS: wer's in die CodeLib stellen will soll es selber tuen Wink
deine arbeit, also musst/darfst du das tun. ehre wem ehre gebührt.
Miniaturansicht angehängter Grafiken
tmemorymappedfile_korrekt_805.jpg  
  Mit Zitat antworten Zitat
bigg
(Gast)

n/a Beiträge
 
#80

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

  Alt 4. Aug 2005, 14:20
@hagen:
die asm-prozedur sieht lustig aus
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 8 von 12   « Erste     678 910     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 01:22 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