![]() |
Re: Eindeutiger Vergleich für große Dateien gesucht
Hab zwar den Code zum Dateivergleich noch nicht gefunden, aber ein Stringvergleich tut es doch auch.
Der Dateivergleich entsprach aber in etwa dem Inhalt der "If Length(S2) > 1 Then"-Bedingung. (hauptsächlich Vergleich der Hash's und bei gleichem Hash nochmal einen byteweisen Vergleich der Daten, damit das Problem gleicher Hash's, trotz unterschiedlicher Rohdaten nicht auftritt) "S2 = Wortliste..." führt eine Funktion aus, welche die Bytes vergleicht und beim ersten Unterschied den Vergleich abbricht, also die gesammten Stringdaten werden fast niemals verglichen/bearbeitet. Und wenn man jetzt mal die beiden Varianten misst, dann wird eine erhebliche Steigerung der Geschwindigkeit dankt der Hash's auffallen. Ein Vergleich ohne Hash's ist halt nur dann schneller, wenn nur ein einziger String, oder eben eine einzige Datei mit einem anderen String / einer anderen Datei verglichen wird. Aber wenn man mehrere Strings/Dateien untereinander vergleicht, sieht das ganz anders aus, da ja sonst jeder String / jede Datei mehrfach eingelesen wird ... beim Hash hat mann dagegen einen netten kleinen Wert zum Vergleich ganz schnell zur Hand. Warum hier unter Umständen nochmals die Strings/Dateien direkt miteinander Verglichen wird, brauch ich dank Nico/Hagen ja nichtnochmal zu erklären. z.B. Zitat:
Input: S z.B. Inhalt einer TextDatei Output: Wortliste Liste aller enthaltenen Wörter bestehend aus 0-9, A-Z, "_" und a-z
Delphi-Quellcode:
Var S, S2: AnsiString;
i, i2, i3, L: Integer; H: LongWord; Wortliste: Array of Record Hash: LongWord; Wort: AnsiString; End; Begin Wortliste := nil; L := Length(S); While (i <= L) and not (S[i] in ['0'..'9', 'A'..'Z', '_', 'a'..'z']) do Inc(i); While i <= L do Begin i2 := i; While (i2 <= L) and (S[i2] in ['0'..'9', 'A'..'Z', '_', 'a'..'z']) do Inc(i2); S2 := Copy(S, i, i2 - i); i := i2; If Length(S2) > 1 Then Begin H := CRC32(S2); i3 := -1; For i2 := High(Wortliste) downto 0 do If (H = Wortliste[i2].Hash) and (S2 = Wortliste[i2].Wort) Then Begin i3 := i2; Break; End; If i3 < 0 Then Begin i3 := Length(Wortliste); SetLength(Wortliste, i3 + 1); Wortliste[i3].Hash := H; Wortliste[i3].Wort := S2; End; End; While (i <= L) and not (S[i] in ['0'..'9', 'A'..'Z', '_', 'a'..'z']) do Inc(i); End; End;
Delphi-Quellcode:
Var S, S2: AnsiString;
i, i2, i3, L: Integer; Wortliste: Array of AnsiString; Begin Wortliste := nil; L := Length(S); While (i <= L) and not (S[i] in ['0'..'9', 'A'..'Z', '_', 'a'..'z']) do Inc(i); While i <= L do Begin i2 := i; While (i2 <= L) and (S[i2] in ['0'..'9', 'A'..'Z', '_', 'a'..'z']) do Inc(i2); S2 := Copy(S, i, i2 - i); i := i2; If Length(S2) > 1 Then Begin i3 := -1; For i2 := High(Wortliste) downto 0 do If S2 = Wortliste[i2].Wort Then Begin i3 := i2; Break; End; If i3 < 0 Then Begin i3 := Length(Wortliste); SetLength(Wortliste, i3 + 1); Wortliste[i3] := S2; End; End; While (i <= L) and not (S[i] in ['0'..'9', 'A'..'Z', '_', 'a'..'z']) do Inc(i); End; End; In etwa so könnte es z.B. für Dateien aussehen:
Delphi-Quellcode:
List: Array of Record
Hash: LongWord; FN: AnsiString; End; H := CRC32File(FileName); i2 := -1; For i := High(List) downto 0 do If (H = List[i].Hash) and CompareFile(FileName, List[i].FN) Then Begin i2 := i; Break; End; If i2 < 0 Then Begin // Datei in die Liste eintragen i2 := Length(List); SetLength(List, i2 + 1); List[i2].Hash := H; List[i2].FN := FileName; End Else Begin // eine Datei mit dem selben Inhalt existiert bereits End; PS: wie Hagen schon sagte, kann man jetzt noch die Dateigöße mit in den Vergleich mit einbeziehen, um nochmeh Geschwindigkeit rauszubekommen. Aber so wie mein DemoCode aufgebaut ist, ist dieses nicht wirklich nötig, da ein weiteres Vergleichskriterium die gesammte Prozedur natürlich erstmal etwas verlangsamt und die erhoffte Beschleunigung nur dann eintreten wird, wenn die Hash's gleich sind ... was ja auch nicht gerade oft vorkommt. Ergo ist ein weiteres Vergleichskriterium, wie Größe/Datum... hierfür unnötig. Aber wie gesagt, wenn man wiederum nur eine Datei mit einer anderen Vergleichen will, können witere Kriterien Wunder bewirken ;) PSS: was ich noch sagen bezöglich der maximalen Dateigröße sagen wollte ... Viele Dateifunktionen arbeiten nur mit 32 Bit ... und obwohl die netten WinAPI-Funktionen auch 64 Bit verstehen können, wird dennoch (meistens) nur mit 32 Bit gearbeitet. Also versagen die meisten Hashfunktionen schon bei Dateien über 2 GB. Die Hashfunktionen mögen ja auch mit mehr als 2 GB umgehen können, aber wenn der Dateiinput dort aufgibt, bringt dieses nun auch nichts. Und da die Dateien/Datenträger immer größer werden, sind mehr als 2 GB nichts exotisches mehr, also hab ich meine UCC und demnach dir darin enthaltenen Hashfunktionen natürlich mit 64-Bit ausgestattet. PS: Ja, das mit dem unverschämten Kopieren ist nicht nett und ich kann sowar ja auch nicht leiden. Ich bin allerdings der Meinung, das es dabei nicht auf bestimmte Regionen ankommt, wie die Programmierer dort damit umgehen. In meinem UCC habe ich zwar das Meißte selbst erstellt und an den entsprechenden Stellen, wo es nicht volltändig aus meiner Feder stammt, wird dieses dann auch erwähnt. [add] och menno ... immer dieser Hagen mit seinen Geheimnissen ... da denkt man mal, man hat 'nen Fehler in seinen Codes gefunden und dann behauptet der doch tatsächlich, das es angeblich richtig so sei :( und wenn man dann die vielen Beiträge dort oben nochmal durchsieht, dann fällt einem auf, daß man sich die Arbeit mit den Codes auch hätte sparen können, weil einiges davon schonmal gesagt wurde :wall: Ich muß unbedingt mal wieder etwas mehr Zeit hier verbringen ... denn bei solchen Themen fällt es doch stark auf, wenn man nicht ständig hier ist ... man kommt einfach nicht mehr hinterher -.-'' so, noch 2 Datei übrig |
AW: Eindeutiger Vergleich für große Dateien gesucht
Mahlzeit,
der Thread ist schon sehr alt, aber ich habe da trotzdem mal eine Frage :-D Ich nutze die FileCompare.pas von negaH (Hagen) um 2 Verzeichnisse (A und B) zu Vergleichen, also Datei für Datei. Dabei nutze ich diese Funktion
Code:
Anschließend werden die unterschiedlichen Dateien synchronisiert (Von A nach B).
function CompareFile(const FileName1, FileName2: String): Boolean; overload;
begin Result := (AnsiCompareText(FileName1, FileName2) = 0) or ((GetFileSize(FileName1) = GetFileSize(FileName2)) and (HashFile(FileName1) = HashFile(FileName2)) and CompareFilePhysical(FileName1, FileName2)); end; Lasse ich nun die Funktion nochmal drüber laufen, findet er wieder Unterschiede (sogar andere Dateien wie vorher), obwohl ich nichts verändert habe. Nehme ich aber aus der Funktion oben den Teil mit der MD4-Überprüfung raus (HashFile), funktioniert es. Ist da vielleicht ein Fehler drin :?: |
AW: Eindeutiger Vergleich für große Dateien gesucht
Zitat:
Ich habe mir nicht den ganzen Thread durchgelesen, aber wenn ich es richtig behalten habe geht Hagen von einer bestimmten "üblichen" Konstellation aus. Ich würde so arbeiten
Code:
Das AnsiCompareText hat mir nichts gebracht, aber das kann natürlich auch an den Dateiinhalten liegen.
if filesize(file1)=filesize(2) then
if hash(file1)=hash(file2) then if binary(file1)=binary(file2) then FileIsEqual Ändern sich die Inhalte einer Datei nicht, ändert sich auch der Hash-Wert nicht. Falls doch ist da etwas faul. U.U. solltest Du da mal ein Vergleichsprotokoll mitlaufen lassen um zu sehen mit welchen Daten Du da hantierst. Gruß K-H |
AW: Eindeutiger Vergleich für große Dateien gesucht
Das AnsiCompare ist ja nur für den Fall, dass man beides Mal den gleichen Dateinamen angibt.
Die sind definitiv gleich, weil diesselbe ;) |
AW: Eindeutiger Vergleich für große Dateien gesucht
:oops: Das kommt davon wenn man nicht richtig liest, Jahre her und trotzdem aufgefallen:oops:
Gruß K-H |
AW: Eindeutiger Vergleich für große Dateien gesucht
Zitat:
Sie wurde also von Hagen dort hinein geschrieben. Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:50 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz