Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Compare Files -> Optimieren (https://www.delphipraxis.net/126701-compare-files-optimieren.html)

cherry 31. Dez 2008 10:45


Compare Files -> Optimieren
 
Liste der Anhänge anzeigen (Anzahl: 3)
Hi @all

hier wahrscheinlich mein letzter Beitrag in diesem Jahr...

Ich habe mir ein kleines Programm geschrieben das rekursiv Dateien von zwei beliebigen Ordnern auf die Aktualität
überprüft und das Ergebnis in ein StringGrid schreibt...

Nun soweit ich es getestet habe funktioniert das ganze auch, bin aber mit der Geschwindikeit nicht zufrieden...
Ich habe einen Geschwindikeitsvergleich mit dem Tool "Total Commander" gemacht und musste feststellen das mein Programm für
den gleichen Vergleich immer etliche Sekunden länger braucht. [-> Vergleich mit 9591 Dateien in über 1000 Ordnern]

Kurz zum Aufbau meines Programms:

Zuerst werden beide angegebenen Ordner rekursiv nach Dateien abgesucht, das Ergebnis wird in einem Array festgehalten.
Anschliessend werden die beiden Arrays verglichen...

Viellecht müsste man die Methodik grundsätzlich überdenken?!
Bin auf Eure verbesserungsvorschläge gespannt!


Im Anhang das ganze Projekt...

:cheers: Guten Rutsch ins neue Jahr

p80286 31. Dez 2008 15:49

Re: Compare Files -> Optimieren
 
Hallo Cherry,

Ich hab gerdade kein Delphi zur Hand darum nur eine theoretische Überlegung:

zunächst, was willst Du mit dem Vergleich erreichen?
1) Du suchst gleiche Dateien mit gleichem Inhalt/gleichem Namen
2) Du suchst unterschiedliche Dateien in Verzeichnissen, die wahrscheinlich gleich oder weitestgehend gleich sind.

Im ersten Fall steckst Du alle Dateinamen und die Dateigrößen in eine Tlist, sortierst nach der Größe und löschst alle Sätze wo es für die Größe keine Doublette gibt. Soll auch der Name gleich sein löschst Du auch die mit unterschiedlichen Namen. Was übrig bleibt, sind die vielleicht doppelten.
Die nimmst Du Dir paarweise und liest die ersten 512...2048 Byte in zwei Arrays ein. Die Größe ist davon abhängig welche Dateien Du vergleichen willst, sprich wo wahrscheinlich der erste Unterschied auftaucht.
Was danach noch übrig bleibt, davon erstellst du eine Prüfsumme (Hash) und wenn die gleich ist,dann hast Du eine inhaltsgleiche Datei.

Im zweiten Fall erstellst Du zwei Listen, eine für das Quell- und eine für das Zielverzeichnist. Aus der Liste des Quellverzeichnisses generierst Du eine weitere Liste,die dem Inhalt des Zielverzeichnisses entsprechen sollte.
vergleiche die Sollliste mit der Zielliste und Du erhälst die Dateien/Dateinamen die nur im Ziel oder Quellverzeichnis enthalten sind.
Die übrigen vergleichst Du nach dem gleichen Schema wie oben, nur das Du diesmal die gleichen Dateien verwirfst und die ungleichen behälst.

Grüße K-H

Luckie 31. Dez 2008 17:08

Re: Compare Files -> Optimieren
 
Zitat:

Zitat von cherry
Anschliessend werden die beiden Arrays verglichen...

Und genau das ist der entscheidende Punkt. WIE vergleichst du? Vergleichst du Byte für Byte oder bildest du über die Dateien einen Hash und verglechst den oder was machst du?

alzaimar 31. Dez 2008 17:26

Re: Compare Files -> Optimieren
 
Man muss sowieso nur die Dateien vergleichen, die eventuell identisch sein könnten. Dateien unterschiedlicher Größe und/oder unterschiedlichen Datums sind eh verschieden. Per Hash würde ich dann auch nicht vergleichen, sondern bis zum auftreten des ersten ungleichen Zeichens. Das dürfte schneller sein.

p80286 31. Dez 2008 23:04

Re: Compare Files -> Optimieren
 
Hallo zusammen und ein gutes neues Jahr,

@alzaimar
auf das gleiche/ungleiche Datum würde ich nicht vergleichen, da mir vor ein paar Jahren ein Novell-Server das Dateidatum "zerbröselt" hat. Auf's Bit gleiche Dateien hatten aus ungeklärten Gründen auf dem Server eine Stunde "Nachlauf", die dann zum Ausgleich beim kopieren auf den Client eine Stunde "Vorlauf" bekamen. Auch wenn die Zeit zwischen zwei Rechner nicht ordentlich syncronisiert, bekommst Du Probleme, darum Finger weg vom Datum(Zeit).

was den Vergleich angeht, hast Du Recht, wenn zu erwarten ist, daß der überwiegende Teil der Dateien ungleich ist. Ist die Zahl der gleichen größer, oder der Unterschied liegt erst am "Ende", dann ist ein Hash schneller. (Zumindestens wenn ein erklecklicher Teil über 5-10 MB liegt)

Grüße
K-H

stahli 1. Jan 2009 11:39

Re: Compare Files -> Optimieren
 
so mache ich das:
(vorab Größe vergleichen und dann blockweise erstes unterschiedliches Zeichen suchen)

Delphi-Quellcode:
procedure TDCustom.CompareFileNow;
const
  BS = 1000;
type
  TBB = array[1..BS] of Byte;
var
  S1, S2: String;
  F1, F2: File of Byte;
  B1, B2: TBB;
  F: Boolean;
  R1, R2, I: Integer;
begin
...
          S1 := FileName;
          S2 := PathCompare + CompareFileName;
          if (S1 <> '') and (S2 <> '') and (S1 <> S2) then
          begin
            if FileExists(S1) then
            begin
              ...
              if FileExists(S2) then
              begin
                F := True;
                AssignFile(F1, S1);
                Reset(F1);
                AssignFile(F2, S2);
                Reset(F2);
                if FileSize(F1) = FileSize(F2) then
                begin
                  repeat
                    BlockRead(F1, B1, Length(B1), R1);
                    BlockRead(F2, B2, Length(B2), R2);
                    if R1 = R2 then
                    begin
                      for I := 1 to R1 do
                      begin
                        if B1[I] <> B2[I] then
                        begin
                          F := False;
                          Break;
                        end;
                      end;
                    end
                    else
                    begin
                      F := False;
                    end;
                  until (not F) or (Eof(F1) and Eof(F2));
                end
                else
                begin
                  F := False;
                end;
                CloseFile(F1);
                CloseFile(F2);
                FFileIsValue := F; // <---
              end;
            end;
          end
          else
...
end;

stahli

alzaimar 1. Jan 2009 13:24

Re: Compare Files -> Optimieren
 
Zitat:

Zitat von p80286
auf das gleiche/ungleiche Datum würde ich nicht vergleichen

Es kann aber trotzdem sein, das sie unterschiedlich sind. Du beschreibst hier ein 'false positive' Ereignis, das nicht zu einem Fehler führt, sondern nur zu einem unnötigem Vergleich. WTF.

Zitat:

Zitat von p80286
Ist die Zahl der gleichen größer, oder der Unterschied liegt erst am "Ende", dann ist ein Hash schneller. (Zumindestens wenn ein erklecklicher Teil über 5-10 MB liegt)

Das verstehe ich nicht.
Bei einer Hashberechnung lese ich eine Datei *vollständig* ein und berechne einen Wert. Das mache ich für beide Dateien.
Bei einem Dateivergleich lese ich auch beide Dateien Stück-für-Stück ein und vergleiche sie. Wo soll da der Geschwindigkeitsvorteil bei der Hashberechnung sein? Sind Hashbberechnungen neuerdings schneller als Vergleiche? :gruebel: Außerdem breche ich doch sowieso beim ersten ungleichen Byten ab. Bei einer angenommenen Gleichverteilung der Unterschiede lese ich also im Mittel nur 50% der Dateien ein. Der Einzige Vorteil eines Hashes wäre, wenn eine Datei A mit mehreren Dateien verglichen werden muss. Dann hätte ich einen Geschwindigkeitsvorteil.
Im Übrigen bedeuten identische Hashes ja nicht notwendigerweise identische Inhalte. Die Wahrscheinlichkeit ist zwar 'eher' gering, aber rein mathematisch gesehen ist ein Dateivergleich per Hash ungenügend, ergo stimmt die E/A-Relation nicht, mithin ist das Programm dann beweisbar falsch.

p80286 1. Jan 2009 19:30

Re: Compare Files -> Optimieren
 
hallo alzaimar,

beim Datum hab ich mich wohl falsch ausgedrückt. Meine Annahme war
gleiche Größe und unterschiedliches Datum=unterschiedliche Datei
und das war falsch! Ich mußte also die Datei selbst vergleichen.

Wie Du richtig ausgeführt hast, ist der Hash nur dann schneller wenn eine Datei mehrmals an einem Vergleich beteiligt ist. Dies ist bei mir der Fall, da z.b. bei drei Dateien mit der gleichen Größe jede Datei mit jeder anderen also (1 mit 2 und 3) und (2 mit 3) verglichen wird.
Aber vielen Dank für die Anregung.
Ich denke an der Vergleichslogik kann ich noch eine Menge feilen.
Was den "Hash" angeht, verwende ich einen Prüfsummenalgorithmus, der vor Urzeiten mal in der Dr. Dobbs gestanden hat, der nach meinen Erfahungen für Dateien gleicher Größe bei ungleichem Inhalt auch ungleiche Werte produziert.
Ich hab auch mal den "Adler" ausprobiert, aber bei dem sind Fehler aufgetreten.
Mit MD5 habe ich auch noch keine Fehler erhalten, aber der ist etwas langsamer als "Dr.Dobbs".

Da ich z.Zt. weit weg bin von meinem Delphi, kann ich nicht konkreter werden.


@stahli:
Entschuldigung Dich hätte ich beinahe vergessen. Du solltest BS ein wenig vergrößern.
Ich glaube an die Magie der 2erPotenzen also 4096,8192 usw.
versuchs mal damit

Grüße
K-H

cherry 1. Jan 2009 22:26

Re: Compare Files -> Optimieren
 
Anscheinend liegen einige Missverständtnisse vor...

Ich will in erster Linie die Dateien zweier nahezu identischen Ordnern auf ihre Aktualität überprufen. Und das übers Datum und nicht über den Inhalt der Dateien...

Das ganze habe ich auch bereits realisiert, nur scheint mir meine Methodik nicht optimal da es offensichtlich auch schneller geht...

Werft doch einfach mal einen Blick auf den Code...

Delphi-Quellcode:
...

// ]]] START COMPARING [[[
procedure TFormMain.Compare;
var
  i,j,c,tmpIndex,tmpIndex2:Integer;
  Dir:String; // Directory Name
  arChecked: array of Integer;
begin

  ClearStringGrid;
  SetLength(arFileRec1,0);
  SetLength(arFileRec2,0);
  SetLength(arChecked,0);
  Dir:='';
  c:=0; // files count
  abort:=false;

  GetTreeList(DirectoryListBox1.Directory, DirectoryListBox1.Directory, '*', CbSubDirs.Checked, True, arFileRec1);
  GetTreeList(DirectoryListBox2.Directory, DirectoryListBox2.Directory, '*', CbSubDirs.Checked, False, arFileRec2);

  for i := low(arFileRec1) to high(arFileRec1) - 1 do
  begin

//    Application.ProcessMessages;
//    if abort then
//      exit;

    if (Dir <> arFileRec1[i].Dir) then
    begin
      Dir:=arFileRec1[i].Dir;
      Write(0,Dir,True);
    end;
    Write(0,arFileRec1[i].Name,True);
    Write(1,IntToStr(arFileRec1[i].Size));
    Write(2,DateTimeToStr(arFileRec1[i].Date));
    tmpIndex:=ArFileRecIndexOfDirName(arFileRec2,arFileRec1[i].DirName);
    Inc(c);
    if (tmpIndex <> -1) then
    begin
      // remember the values already checked ...
      SetLength(arChecked,Length(arChecked)+1);
      arChecked[Length(arChecked)-1]:=tmpIndex;
      // at least compare date values ...
      case CompareDate(arFileRec1[i].Date,arFileRec2[tmpIndex].Date) of
        fdsNewer: begin Write(3,'>'); end;
        fdsOlder: begin Write(3,'<'); end;
        fdsSameDate: begin Write(3, '=') end;
      end;
      Write(4,DateTimeToStr(arFileRec2[tmpIndex].Date));
      Write(5,IntToStr(arFileRec2[tmpIndex].Size));
      Write(6,arFileRec2[tmpIndex].Name);
    end
    else
    begin
      Write(3,'>');
      tmpIndex2:=arFileRecIndexOfDir(arFileRec2,arFileRec1[i].Dir,0);
      if tmpIndex2 <> -1 then
      begin
        for j := tmpIndex2 to high(arFileRec2) - 1 do
        begin
          if not IntArray_Contains(arChecked,j) then
          begin
            if arFileRecIndexOfDir(arFileRec2,arFileRec1[i].Dir,j) <> -1 then
            begin
              if (arFileRecIndexOfDirName(arFileRec1,arFileRec2[j].DirName) = -1)
                and (arFileRec1[i].Dir = arFileRec2[j].Dir) then
              begin
                Write(3,'<',True);
                Write(4,DateTimeToStr(arFileRec2[j].Date));
                Write(5,IntToStr(arFileRec2[j].Size));
                Write(6,arFileRec2[j].Name);
                // remember the values already checked ...
                SetLength(arChecked,Length(arChecked)+1);
                arChecked[Length(arChecked)-1]:=j;
                Inc(c);
              end
            end
            else
              break;
          end;
        end;
      end;
    end;
  end;

  Dir:='';

  // maby there exists folders unique on the right ...
  for i := low(arFileRec2) to high(arFileRec2) - 1 do
  begin

//    Application.ProcessMessages;
//    if abort then
//      exit;

    if not IntArray_Contains(arChecked,i) then
    begin
      if (Dir <> arFileRec2[i].Dir) then
      begin
        Dir:=arFileRec2[i].Dir;
        Write(0,Dir,True);
      end;
      Write(3,'<',True);
      Write(4,DateTimeToStr(arFileRec2[i].Date));
      Write(5,IntToStr(arFileRec2[i].Size));
      Write(6,arFileRec2[i].Name);
      Inc(c);
    end;
  end;

  Statusbar1.Panels[0].Text := ' files found: '+IntToStr(c);
  BtnCompare.Enabled:=True;
  BtnAbort.Enabled:=False;

end;

...
Das ganze Projekt ist wie gesagt im ersten Beitrag gepostet...

p80286 2. Jan 2009 03:12

Re: Compare Files -> Optimieren
 
hallo Cherry,

Ich habe z.Zt. keine Möglichkeit Deinen Code herunter zu laden, darum nur so aus der Hüfte:
Du verwendest sehr viele write, und die kosten Zeit!

grüße
K-H

alzaimar 2. Jan 2009 07:55

Re: Compare Files -> Optimieren
 
Neben dem Logging (per 'Write') würde ich folgende Operationen als Performancebremse ansehen:
1. 'GetTreeList'
2. 'arFileRecIndexOfDir'.

Bei (1) hilft ein schnelleres Verfahren zum Auslesen einer Verzeichnisstruktur (gibts hier oder im der Delphi-Forum, weiss nicht mehr genau)
Bei (2) wäre der Code interessant. Ich tippe auf eine einfache For-Schleife und das kann man wesentlich schneller machen, z.B. durch eine Hashmap. Und sowas gibt es als 'TStringDictionary' auch hier.

cherry 2. Jan 2009 10:25

Re: Compare Files -> Optimieren
 
Zitat:

Zitat von p80286
Du verwendest sehr viele write

naja, irgendwie muss ich ja das StringGrid abfüllen... wie soll ich denn das sonst lösen?


Zitat:

Zitat von alzaimar
1. 'GetTreeList'
2. 'arFileRecIndexOfDir'.
Bei (1) hilft ein schnelleres Verfahren zum Auslesen einer Verzeichnisstruktur (gibts hier oder im der Delphi-Forum, weiss nicht mehr genau)
Bei (2) wäre der Code interessant. Ich tippe auf eine einfache For-Schleife und das kann man wesentlich schneller machen, z.B. durch eine Hashmap. Und sowas gibt es als 'TStringDictionary' auch hier.

zu 1, ist ein bisschen waage ausgedrückt, wie soll ich das denn finden? und überhaupt, hast du dir den code eigentlich angesehen zu 'GetTreeList'?

zu 2, ja da hast du recht, is nur eine for schleiffe... werde mich mal mit sonem 'TStringDictionary'
versuchen anzufreunden, habe ich allerdings noch nie verwendet. Ist das eine StdKomponente von Delphi?

himitsu 4. Jan 2009 13:57

Re: Compare Files -> Optimieren
 
also, ch hab jetzt noch garnicht groß in deinen QuellCode reingesehn, aber beim ersten Testlauf bekam ich nach nichtmal 'ner Minute dieses hier
Zitat:

---------------------------
Benachrichtigung über Debugger-Exception
---------------------------
Im Projekt CompareFiles.exe ist eine Exception der Klasse EOutOfMemory aufgetreten. Meldung: 'Zu wenig Arbeitsspeicher'. Prozess wurde angehalten. Mit Einzelne Anweisung oder Start fortsetzen.
---------------------------
OK Hilfe
---------------------------
gelesene Verzeichnisse ~830
Speicher laut Taskmanager ~190 MB (von deinem Programm) und insgesamt noch knapp 1,5 GB frei

Insgesamt würde es, von der Programmstruktur und den verwendeten Komponenten her, vermutlich aber eh Probleme mit vielen Dateien geben (war es wohl nicht sonderlich gut, von mir, deinem Programm gleich mal 2 "kleine" Festplatten zum Vergleich zu geben)

Beim 2. Versuch, nur mit meinem USB-Stick und seinem Backup (je 26.506 Dateien und ~2 GB belegt) kommt der selbe Fehler.


nja, auch wenn es nicht jeder baucht ... mit den japanischen, russischen und ähnlichen Dateinamen auf meinem Plättchen gib es sowieso Probleme.


PS: Pegasus (Luckie), hSync (/me) und Weitere, derartige Programme findest in der DP

[add] unter 100 Dateien in 'nem Verzeichnis scheint der Vergleich erstmal korrekt zu funktionieren

alzaimar 5. Jan 2009 12:18

Re: Compare Files -> Optimieren
 
Zitat:

Zitat von cherry
... hast du dir den code eigentlich angesehen zu 'GetTreeList'?

Na nee? Wo isser denn?
Zitat:

Zitat von cherry
zu 2, ja da hast du recht,... Ist das eine StdKomponente von Delphi?

Zitat:

Zitat von alzaimar
...Und sowas gibt es als 'TStringDictionary' auch hier.

"auch hier" = Suche-Funktion in der Delphi-Praxis.

cherry 6. Jan 2009 06:13

Re: Compare Files -> Optimieren
 
Zitat:

Zitat von alzaimar
Zitat:

Zitat von cherry
... hast du dir den code eigentlich angesehen zu 'GetTreeList'?

Na nee? Wo isser denn?

Im ersten Beitrag findest du gleich das ganze Projekt...

alzaimar 6. Jan 2009 06:22

Re: Compare Files -> Optimieren
 
Oh. Gut. Die Standard-Vorgehensweise. Hier oder im Delphi-Forum wurde ein kleiner Wettbewerb gestartet, welches Tool denn nun schneller ist (um Dateinamen zu suchen). Die Vorgehensweise könnte Dir jedoch helfen, denn 'FindFirst/FindNext' hat wohl einen ganz schönen Overhead.

Für den Rest habe ich derzeit leider keine Zeit. Heut Abend kann ich mal reinschauen.

cherry 6. Jan 2009 06:25

Re: Compare Files -> Optimieren
 
Zitat:

Zitat von alzaimar
Hier oder im Delphi-Forum wurde ein kleiner Wettbewerb gestartet, welches Tool denn nun schneller ist (um Dateinamen zu suchen). Die Vorgehensweise könnte Dir jedoch helfen, denn 'FindFirst/FindNext' hat wohl einen ganz schönen Overhead.

Ist ja praktisch für mich...

Zitat:

Zitat von alzaimar
Für den Rest habe ich derzeit leider keine Zeit. Heut Abend kann ich mal reinschauen.

Das wäre echt super. Vielen Dank schon mal...

cherry 6. Jan 2009 15:28

Re: Compare Files -> Optimieren
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von p80286
Du verwendest sehr viele write, und die kosten Zeit!
grüße
K-H

Deshalb habe ich den Code jetzt nochmals ein wenig angepasst...
allerdings spare ich nicht allzuviel Zeit ein. Bei meinem vergleich mit ~10'000 und ~2'000 Ordnern war das Programm
jetzt immerhin 2 Sekunden schneller und brauchte aber insgesammt immer noch 6 Sekunden.

Das ist aber immer noch min. 2 Sekunden zu langsam und

Zitat:

Zitat von himitsu
Insgesamt würde es, von der Programmstruktur und den verwendeten Komponenten her, vermutlich aber eh Probleme mit vielen Dateien geben (war es wohl nicht sonderlich gut, von mir, deinem Programm gleich mal 2 "kleine" Festplatten zum Vergleich zu geben)

Beim 2. Versuch, nur mit meinem USB-Stick und seinem Backup (je 26.506 Dateien und ~2 GB belegt) kommt der selbe Fehler.

dieses Problem ist ja auch noch zu lösen, wobei die Idee ja nicht umbedingt ist zwei Festplatten zu überprüfen, oder braucht das jmd?! wie auch immer -> es dürfte keinen Absturz verursachen...

Delphi-Quellcode:
// ]]] START COMPARING [[[
procedure TFormMain.Compare;
var
  i,j,c,tmpIndex,tmpIndex2,ri:Integer;
  Dir:String; // Directory Name
  arChecked: array of Integer;
  arRow: TRowArray;
begin

  ClearStringGrid;
  SetLength(arFileRec1,0);
  SetLength(arFileRec2,0);
  SetLength(arChecked,0);
  SetLength(arRow,0);
  Dir:='';
  c:=0; // files count
  abort:=false;

  GetTreeList(DirectoryListBox1.Directory, DirectoryListBox1.Directory, '*', CbSubDirs.Checked, True, arFileRec1);
  GetTreeList(DirectoryListBox2.Directory, DirectoryListBox2.Directory, '*', CbSubDirs.Checked, False, arFileRec2);

  for i := low(arFileRec1) to high(arFileRec1) - 1 do
  begin

//    Application.ProcessMessages;
//    if abort then
//      exit;

    if (Dir <> arFileRec1[i].Dir) then
    begin
      Dir:=arFileRec1[i].Dir;
      SetLength(arRow,Length(arRow)+1);
      arRow[Length(arRow)-1].Name:=Dir;
    end;

    ri:=Length(arRow);
    SetLength(arRow,ri+1);

    arRow[ri].Name:=arFileRec1[i].Name;
    arRow[ri].Size:=IntToStr(arFileRec1[i].Size);
    arRow[ri].Date:=DateTimeToStr(arFileRec1[i].Date);

    tmpIndex:=ArFileRecIndexOfDirName(arFileRec2,arFileRec1[i].DirName);
    Inc(c);
   
    if (tmpIndex <> -1) then
    begin
      // remember the values already checked ...
      SetLength(arChecked,Length(arChecked)+1);
      arChecked[Length(arChecked)-1]:=tmpIndex;
      // at least compare date values ...
      case CompareDate(arFileRec1[i].Date,arFileRec2[tmpIndex].Date) of
        fdsNewer: begin arRow[ri].Sign:='>'; end;
        fdsOlder: begin arRow[ri].Sign:='<'; end;
        fdsSameDate: begin arRow[ri].Sign:='='; end;
      end;
      arRow[ri].Date2:=DateTimeToStr(arFileRec2[tmpIndex].Date);
      arRow[ri].Size2:=IntToStr(arFileRec2[tmpIndex].Size);
      arRow[ri].Name2:=arFileRec2[tmpIndex].Name;
    end
    else
    begin
      arRow[ri].Sign:='>';
      tmpIndex2:=arFileRecIndexOfDir(arFileRec2,arFileRec1[i].Dir,0);
      if tmpIndex2 <> -1 then
      begin
        for j := tmpIndex2 to high(arFileRec2) - 1 do
        begin
          if not IntArray_Contains(arChecked,j) then
          begin
            if arFileRecIndexOfDir(arFileRec2,arFileRec1[i].Dir,j) <> -1 then
            begin
              if (arFileRecIndexOfDirName(arFileRec1,arFileRec2[j].DirName) = -1)
                and (arFileRec1[i].Dir = arFileRec2[j].Dir) then
              begin
                arRow[ri].Sign:='<';
                arRow[ri].Date2:=DateTimeToStr(arFileRec2[j].Date);
                arRow[ri].Size2:=IntToStr(arFileRec2[j].Size);
                arRow[ri].Name2:=arFileRec2[j].Name;
                // remember the values already checked ...
                SetLength(arChecked,Length(arChecked)+1);
                arChecked[Length(arChecked)-1]:=j;
                Inc(c);
              end
            end
            else
              break;
          end;
        end;
      end;
    end;
  end;

  Dir:='';

  // maby there exists folders unique on the right ...
  for i := low(arFileRec2) to high(arFileRec2) - 1 do
  begin

//    Application.ProcessMessages;
//    if abort then
//      exit;

    if not IntArray_Contains(arChecked,i) then
    begin
      if (Dir <> arFileRec2[i].Dir) then
      begin
        Dir:=arFileRec2[i].Dir;
        SetLength(arRow,Length(arRow)+1);
        arRow[Length(arRow)-1].Name:=Dir;
      end;

      ri:=Length(arRow);
      SetLength(arRow,ri+1);

      arRow[ri].Sign:='<';
      arRow[ri].Date2:=DateTimeToStr(arFileRec2[i].Date);
      arRow[ri].Size2:=IntToStr(arFileRec2[i].Size);
      arRow[ri].Name2:=arFileRec2[i].Name;
      Inc(c);
    end;
  end;

  Statusbar1.Panels[0].Text := ' files found: '+IntToStr(c);
  BtnCompare.Enabled:=True;
  BtnAbort.Enabled:=False;

  StringGrid1.RowCount:=Length(arRow);
  for i := 1 to Length(arRow) do
  begin
    StringGrid1.Cells[0,i]:=arRow[i].Name;
    StringGrid1.Cells[1,i]:=arRow[i].Size;
    StringGrid1.Cells[2,i]:=arRow[i].Date;
    StringGrid1.Cells[3,i]:=arRow[i].Sign;
    StringGrid1.Cells[4,i]:=arRow[i].Date2;
    StringGrid1.Cells[5,i]:=arRow[i].Size2;
    StringGrid1.Cells[6,i]:=arRow[i].Name2;
  end;

end;
Im Anhang noch das aktualisierte Projekt...

cherry 7. Jan 2009 13:33

Re: Compare Files -> Optimieren
 
Zitat:

Zitat von alzaimar
Ich tippe auf eine einfache For-Schleife und das kann man wesentlich schneller machen, z.B. durch eine Hashmap. Und sowas gibt es als 'TStringDictionary' auch hier.

Ok, i bin gerade drann das mal mit TStringDictionary resp. mit TIntegerDictionary zu versuchen statt mit meinen Arrays...
Die Klasse habe ich hier gefunden: http://www.delphipraxis.net/internal...ct.php?t=53653

Nur habe ich ein grosses Problem: Ich kappier nicht ganz wie die funzt. Zunächstmal wenn ich einen Wert adden will mit der
Procedure Add(aKey: Cardinal; aData: Pointer) ...

Wieso einen Pointer, ich will doch einen Stringwert hineinschreiben?! wie mach ich das nun?


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:25 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