Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   File compare (https://www.delphipraxis.net/160642-file-compare.html)

value is NULL 24. Mai 2011 10:45

File compare
 
Hi Leutz

Ich weiß es gibt schon einige Threads darüber aber ich habe noch keine brauchbare Lösung gefunden.

Ich will praktisch 2 Files miteinander vergleichen und sobald sich die eine von der anderen in irgendeiner Art und Weise unterscheidet (Inhaltlich) reagieren?

Wie könnte das realisiert werden?

LG

DeddyH 24. Mai 2011 10:48

AW: File compare
 
Eine Möglichkeit: beide Dateien in jeweils einen Stream einlesen und beide Streams mit CompareMem vergleichen.

value is NULL 24. Mai 2011 10:54

AW: File compare
 
dh mit:

Delphi-Quellcode:
 Stream := TFileStream.Create('c:\Temp\StreamTest.Datei', fmOpenRead);
auslesen und dann zB mit folgender funktion vergleichen:

Delphi-Quellcode:
function CompareMem(P1, P2: PChar; Length: Integer): Boolean;
begin
  Result := False;
  while Length > 0 do
    if P1^ = P2^ then
    begin
      Dec(Length);
      Inc(P1);
      Inc(P2);
    end else Exit;
  Result := True;
end;
?

LG

Luckie 24. Mai 2011 10:55

AW: File compare
 
Erstelle von beiden Dateien eine Hash und vergleiche diesen.

mleyen 24. Mai 2011 10:59

AW: File compare
 
Thread: http://www.delphipraxis.net/50896-ei...n-gesucht.html
Ergebnis: http://www.delphipraxis.net/51018-da...rgleichen.html

Funzt ganz gut. :-D

value is NULL 24. Mai 2011 11:00

AW: File compare
 
@ Lucki

mit der MD5.pas zB aus http://www.koders.com/delphi/fid1C4B...6FB7FC2BA.aspx

ich nehme mal an ich muss MDFile aufrufen und anschließend MD5Match?

Leider noch nicht mit sowas zu tun gehabt !

LG

DeddyH 24. Mai 2011 11:04

AW: File compare
 
Ungetestet:
Delphi-Quellcode:
function FilesAreEqal(const First, Second: TFilename): Boolean;
var
  FirstStream, SecondStream: TMemoryStream;
begin
  Result := FileExists(First) and FileExists(Second);
  if Result then
    begin
      FirstStream := TMemoryStream.Create;
      try
        SecondStream := TMemoryStream.Create;
        try
          FirstStream.LoadFromFile(First);
          SecondStream.LoadFromFile(Second);
          Result := FirstStream.Size = SecondStream.Size;
          if Result then
            begin
              FirstStream.Position := 0;
              SecondStream.Position := 0;
              Result := CompareMem(FirstStream.Memory, SecondStream.Memory);
            end;
        finally
          SecondStream.Free;
        end;
      finally
        FirstStream.Free;
      end;
    end;
end;

p80286 24. Mai 2011 11:45

AW: File compare
 
Für die ganz schnellen, erst die Größe der beiden Dateien vergleichen!

Gruß
K-H

Deep-Sea 24. Mai 2011 11:48

AW: File compare
 
@DeddyH:
Dann lade mal bitte zwei 20GB große Dateien in den Arbeitsspeicher :P


PS: Hashen lohnt sich eig. erst, wenn man mehrere Dateien mit einer vergleichen will.

value is NULL 24. Mai 2011 12:05

AW: File compare
 
ich mache es jetzt mit der FileCompare unit!
Funktioniert perfekt!

danke!

DeddyH 24. Mai 2011 12:22

AW: File compare
 
Zitat:

Zitat von Deep-Sea (Beitrag 1102540)
@DeddyH:
Dann lade mal bitte zwei 20GB große Dateien in den Arbeitsspeicher :P

Hab ich etwa gesagt, dass ich hier mal eben die ultimative Routine aus dem Handgelenk schreibe? Es ging ja nur darum, das vorher angedeutete Prinzip in Code zu formulieren. Wenn ich natürlich gewusst hätte, das Hagen da schon was Fertiges in petto hat, hätte ich mir die Mühe gespart :)

value is NULL 24. Mai 2011 12:26

AW: File compare
 
Kann ich auch irgendwie herausfinden, was genau sich geändert hat? zB die betroffene Zeile?

LG

DeddyH 24. Mai 2011 12:28

AW: File compare
 
Geht es nur um Textdateien? Ansonsten gibt es ja keine Zeilen.

value is NULL 24. Mai 2011 12:34

AW: File compare
 
^jap ich vergleiche praktisch 2 textdateien!

LG

DeddyH 24. Mai 2011 12:35

AW: File compare
 
Die kannst Du doch einfach zeilenweise einlesen und vergleichen.

stahli 24. Mai 2011 12:46

AW: File compare
 
Nur mal noch bezüglich Gleichheitsprüfung:
Vorausgesetzt, die Texdateien sind nicht zu groß, könnte man sie einfach in 2 TStringList laden und auf
Delphi-Quellcode:
SL1.Text = SL2.Text
prüfen. Zumindest wäre das ein recht unkomplizierter Weg.

DeddyH 24. Mai 2011 12:47

AW: File compare
 
Damit bekommst aber keine Zeilennummer bei evtl. Unterschieden ;)

value is NULL 24. Mai 2011 13:00

AW: File compare
 
so in etwa?

ich mein sieht grauslich aus aber wäre das prinzip richtig?

Delphi-Quellcode:
    i := 0;
    i2 := 0;
    countsum := getlinecount('C:\myfile.txt');
    sl := TStringlist.Create;
    sl2 := TStringlist.Create;
    sl.loadfromfile('C:\myfile.txt');
    sl2.loadfromfile('C:\my2ndFile.txt');
    while i < countsum do begin
        i := i + 1;
        i2 := i2 + 1;
        if sl[i] = sl[i2] then writeln('Kein Unterschied');
    end;
...

DeddyH 24. Mai 2011 13:08

AW: File compare
 
Ungetestet:
Delphi-Quellcode:
function FilesEqual(const First, Second: TFilename; out DiffLine: integer): Boolean;
var
  s1, s2: TStringlist;
  i: integer;
begin
  Result := FileExists(First) and FileExists(Second);
  if Result then
    begin
      s1 := TStringlist.Create;
      try
        s1.LoadFromFile(First);
        s2 := TStringlist.Create;
        try
          s2.LoadFromFile(Second);
          i := 0;
          while (i < s1.Count) and (i < s2.Count) do
            begin
              Result := s1[i] = s2[i];
              if not Result then
                begin
                  DiffLine := i;
                  i := s1.Count;
                end;
              inc(i);
            end;
        finally
          s2.Free;
        end;
      finally
        s1.Free;
      end;
    end;
end;

himitsu 24. Mai 2011 13:29

AW: File compare
 
Delphi-Quellcode:
  Result := FileExists(First) and FileExists(Second);
  if Result then
    begin
      s1 := TStringlist.Create;
      try
        s2 := TStringlist.Create;
        try
          s1.LoadFromFile(First);
          s2.LoadFromFile(Second);
          Result := s1.Count = s2.Count
          if Result then
            begin
              i := 0;
              while (i < s1.Count) and (i < s2.Count) do
                begin
                  Result := s1[i] = s2[i];
                  if not Result then
                    begin
                      DiffLine := i;
                      Break;
                    end;
                  inc(i);
                end;
            end
          else
            DiffLine := Min(s1.Count, s2.Count);
        finally
          s2.Free;
        end;
      finally
        s1.Free;
      end;
    end;

value is NULL 24. Mai 2011 13:42

AW: File compare
 
was passiert aber wenn mehrere lines nicht gleich sind.. result ist doch immer nur 1 Wert?

DeddyH 24. Mai 2011 13:45

AW: File compare
 
Klar, die erste unterschiedliche Zeile. Ansonsten musst Du es halt so umbauen/erweitern, dass eine Liste hinten rauskommt.

value is NULL 24. Mai 2011 14:09

AW: File compare
 
hm habe folgende function:

Delphi-Quellcode:
function FilesEqual(const First, Second: TFilename; out DiffLine: integer): Boolean;
var
  s1, s2: TStringlist;
  i: integer;
begin
  Result := FileExists(First) and FileExists(Second);
  if Result then
    begin
      s1 := TStringlist.Create;
      try
        s1.LoadFromFile(First);
        s2 := TStringlist.Create;
        try
          s2.LoadFromFile(Second);
          i := 0;
              while (i < s1.Count) and (i < s2.Count) do
              begin
                Result := s1[i] = s2[i];
                if not Result then
                  begin
                    DiffLine := i;
                    i := s1.Count;
                    s3.Add(s1[i]);
                  end;
                  inc(i);
                end;
        finally
          s2.Free;
        end;
      finally
        s1.Free;
      end;
    end;
end;
und rufe das auf:

Delphi-Quellcode:
    test_functions.FilesEqual('C:\software.txt','C:\software2.txt',i);
    i2 := 0;
    for i2 := 0 to vlxsysstate_functions.s3.Count -1 do
        Writeln(s3[i2]);
    test_functions.s3.Free;
bekomme aber permanent folgendes:

EStringListError: Listenindex ³berschreitet das Maximum (166)

was ist da falsch?

DeddyH 24. Mai 2011 14:14

AW: File compare
 
Wo kommt denn das s3 in der Funktion jetzt her?

p80286 24. Mai 2011 14:17

AW: File compare
 
und in welcher Zeile tritt der Fehler auf?

Gruß
K-H

und das ist doch nicht Dein Ernst oder?
Delphi-Quellcode:
begin
                    DiffLine := i;
                    i := s1.Count;
                    s3.Add(s1[i]);
                  end;

value is NULL 24. Mai 2011 14:21

AW: File compare
 
s3 ist in meiner test_functions unit deklariert

welche zeile kann ich leider nicht sagen da er sich beim debug bei folgendem aufruf:

Delphi-Quellcode:
test_functions.FilesEqual('C:\software.txt','C:\software2.txt',i);
verabschiedet...

Wieso was ist daran so schlimm?

LG

DeddyH 24. Mai 2011 14:25

AW: File compare
 
Ich habe das ungute Gefühl, dass Du nicht genau weißt, was Du da tust.

[edit] i steht auf Anzahl der Listenelemente, anschließend willst Du diesen nicht existenten Eintrag dann an s3 anhängen. Wie soll das funktionieren? [/edit]

p80286 24. Mai 2011 14:25

AW: File compare
 
Zum einen, empfehle ich das Debuggen mit Hilfe von [F7], zum anderen ist
Delphi-Quellcode:
i:=s1.count;
s3.add(s1[i]);
tödlich.

Gruß
K-H

DeddyH 24. Mai 2011 14:27

AW: File compare
 
Und übergib s3 als Parameter, das ist ja gruselig so.

p80286 24. Mai 2011 14:28

AW: File compare
 
Zitat:

Zitat von DeddyH (Beitrag 1102596)
Und übergib s3 als Parameter, das ist ja gruselig so.

Testen ist auch ohne so etwas gruselig :-)

Gruß
K-H

DeddyH 24. Mai 2011 14:36

AW: File compare
 
Also nochmal aufgebohrt (aber immer noch nicht getestet^^):
Delphi-Quellcode:
function FilesEqual(const First, Second: TFilename; DiffList: TStrings): Boolean;
var
  s1, s2: TStringlist;
  i: integer;
begin
  Assert(Assigned(DiffList));
  Result := FileExists(First) and FileExists(Second);
  if Result then
    begin
      DiffList.BeginUpdate;
      try
        DiffList.Clear;
        s1 := TStringlist.Create;
        try
          s1.LoadFromFile(First);
          s2 := TStringlist.Create;
          try
            s2.LoadFromFile(Second);
            i := 0;
            while (i < s1.Count) and (i < s2.Count) do
              begin
                if s1[i] <> s2[i] then
                  DiffList.AddObject(s1[i], TObject(i));
                inc(i);
              end;
          finally
            s2.Free;
          end;
        finally
          s1.Free;
        end;
      finally
        DiffList.EndUpdate;
      end;
      Result := DiffList.Count = 0;
    end;
end;

value is NULL 24. Mai 2011 14:40

AW: File compare
 
OK, bin halt eher unskilled, habs jetzt aber, zumindest funktionierts :)

Delphi-Quellcode:
function test(const First, Second: TFilename; out stringL: TStringlist): Boolean;
var
  s1, s2: TStringlist;
  i: integer;
begin
  Result := FileExists(First) and FileExists(Second);
  if Result then
    begin
      s1 := TStringlist.Create;
      try
        s1.LoadFromFile(First);
        s2 := TStringlist.Create;
        try
          s2.LoadFromFile(Second);
          i := 0;
              while (i < s1.Count) and (i < s2.Count) do
              begin
                Result := s1[i] = s2[i];
                if not Result then
                  begin
                    stringL.Add(s1[i]);
                    //i := s1.Count;
                  end;
                  inc(i);
                end;
        finally
          s2.Free;
        end;
      finally
        s1.Free;
      end;
    end;
end;
aufruf:

Delphi-Quellcode:
    try
      sl := TStringlist.Create;
      test_functions.test('C:\software.txt','C:\software2.txt',sl);
      Writeln(sl.Text);
    finally
      sl.Free;
    end;
Könnte man hier etwas aussetzen ?

LG

Uwe Raabe 24. Mai 2011 14:42

AW: File compare
 
Zitat:

Zitat von value is NULL (Beitrag 1102601)
Delphi-Quellcode:
function test(const First, Second: TFilename; out stringL: TStringlist): Boolean;

Das mit dem "out" würde ich mir nochmal überlegen. Einfach gar nichts hinschreiben, dann passt es schon.

DeddyH 24. Mai 2011 14:44

AW: File compare
 
Da Deine Funktion nach dem ersten bemerkten Unterschied aussteigt, kannst Du auch auf die Stringliste verzichten und gleich einen String als Var-Parameter übergeben. Und ein Objekt als out-Paramter ist nicht das Wahre. Willst Du alle Unterschiede (zumindest die, die innerhalb der minimalen Zeilenanzahl beider Dateien liegen) auflisten, schau Dir einmal meine letzte Version an, die speichert auch die Zeilennummer mit (wenn auch etwas versteckt als TObject).

Jumpy 24. Mai 2011 15:41

AW: File compare
 
Als Advocatus Diaboli ein Einwurf zum Nachdenken. Nicht an DeddyH's Lösung, sondern an das, was man erreichen will:

Wenn du 1000 Zeilen hast, in einer Datei aber eine neue Zeile an z.B. Stelle 3 eingefügt wurde, dann sind die Dateien bis auf diese eine Zeile gleich, du bekommst aber 997 Fehler.

DeddyH 24. Mai 2011 15:42

AW: File compare
 
Daran hatte ich auch schon gedacht, aber wie will man das verhindern?

[edit] Abgesehen davon kann das ja auch richtig sein, je nachdem, was man beabsichtigt. [/edit]

p80286 24. Mai 2011 15:46

AW: File compare
 
Ins unreine gedacht,
für jede Zeile einen Hash-wert erstellen und gleiche Zeilen/Hash-werte aus dem Topf entfernen.
Was übrig bleibt ist nicht gleich.

Gruß
K-H

Jumpy 24. Mai 2011 15:48

AW: File compare
 
[edit]Bezieht sich auf #36, war zu lahm[/edit]

Kannste nicht verhindern. Man kann jetzt die Fuzzy-Pistole rausholen und Ähnlichkeitsanalysen machen usw. aber wie du schon sagst: Es hängt davon ab, was man damit machen will und vllt. ist es genauso schon beabsichtigt.

value is NULL 24. Mai 2011 17:46

AW: File compare
 
hm ihr habt recht... Die Idee von mir ist momentan zerstört :)

Der Plan war eigentlich mir alle installierten programme und windows patches auszulesen. Diese speichere ich in ein Textfile.

anschließend starte ich das Programm neu und lese mir die programme erneut ein, dann werden die frisch eingelesenen mit dem vorhin abgelegten file verglichen.

Sollte sich etwas geändert haben reagiere ich dementsprechend... Das File ändert sich NIE, habe dazu einen Pararmeter eingebaut der die Liste bei bedarf neu erstellt.

Wie könnte ich das realisieren? Die Funktion zum auslesen der Programme über die Registry funktioniert eigentlich prima aber die compare geschichte zerbricht mir den Kopf!

LG

blauweiss 24. Mai 2011 17:57

AW: File compare
 
Hallo value is NULL,

wenn's nur um den Abgleich zweier Listen geht, dann gehe doch einfach die zweite Liste durch und prüfe mit Liste1.IndexOf ab, ob der jeweilige Eintrag dort drin ist. Ggfs. das Gleiche andersrum (Liste1 gegen Liste 2), um gelöschte Einträge zu finden.

Gruß
blauweiss


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:35 Uhr.
Seite 1 von 2  1 2      

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