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/)
-   -   Dateiliste gefiltert erstellen (https://www.delphipraxis.net/213604-dateiliste-gefiltert-erstellen.html)

DieDolly 24. Aug 2023 15:21

Dateiliste gefiltert erstellen
 
Der Titel klingt vielleicht etwas komisch. Aber grob erklärt.

Mit Winapi.Windows.FindFirstFileEx, ganz normal wie man das so kennt, gehe ich durch ein Verzeichnis. Zu jeder Datei und jedem Verzeichnis erstelle ich ein Objekt, welches in eine Liste kommt. Das funktioniert rasend schnell und reicht mir vollkommen so wie es ist.

Ich möchte aber bevor ein Objekt überhaupt erstellt wird prüfen, ob der Dateiname bei dem FindFirstFileEx() gerade dran ist in einer zweiten Liste vorkommt. Falls ja, soll das Objekt am Ende nicht erzeugt werden.

Die zweite Liste enthält nur halbe Pfade also beispielsweise so
Sub1\Sub2\File1.exe
FileX.exe
Sub1\FileY.exe

Das Hauptverzeichnis speichere ich dort nicht mit, da das zu große Dateien zum Speichern geben würde.

Wie kann ich mit Winapi.Windows.FindFirstFileEx() nun Dateien aussortieren, die in der zweiten Liste vorkommen?
Bei 1000 Dateien dauert das aktuell 4 Sekunden, wenn ich 400 davon aussortieren lassen möchte. Ohne Aussortieren dauert das Erzeugen der Objekte rund 10 Millisekunden.

Nathan 24. Aug 2023 15:29

AW: Dateiliste gefiltert erstellen
 
Ich würde zum Filtern nicht mehr direkt die WinAPI verwenden sondern nur noch TDirectory.GetFiles.

Delphi-Quellcode:
ListOfFromFiles := TDirectory.GetFiles(FCopyFrom, '*', TSearchOption.soAllDirectories, Predicate);
Predicate kann dann noch mehr filtern. Beispiel:

Delphi-Quellcode:
  Predicate :=
    function(const Path: string; const SearchRec: TSearchRec): Boolean
    begin
      Result := not string(SearchRec.Name).IsEmpty;
    end;

DieDolly 24. Aug 2023 15:37

AW: Dateiliste gefiltert erstellen
 
Wie lässt sich GetFiles mit meiner zweiten Liste kombinieren?

himitsu 24. Aug 2023 15:38

AW: Dateiliste gefiltert erstellen
 
* Ein Delphi-Referenz durchsuchenMatchText, direkt auf's Array, geht ja nicht, für TeilStrings.
* Am Einfachsten mit Delphi-Referenz durchsuchenEndsText, aber ich würde noch ein '\' davor hängen, weil
Delphi-Quellcode:
EndsText('FileX.exe', 'C:\dir\FileX.exe') = True
EndsText('FileX.exe', 'C:\dir\absadsadFileX.exe') = True
EndsText('\' + 'FileX.exe', 'C:\dir\absadsadFileX.exe') = False
wobei hier natürlich wäre direkt
Delphi-Quellcode:
if ExtractFilenName('C:\dir\FileX.exe') = 'FileX.exe'
besser
bzw.
Delphi-Quellcode:
if MatchText(ExtractFilenName('C:\dir\FileX.exe'), ['FileX.exe', Xyz.exe])

aber
Delphi-Quellcode:
EndsText('dir\FileX.exe', 'C:\dir\FileX.exe') = True
EndsText('dir\FileX.exe', 'C:\absadsaddir\FileX.exe') = True
EndsText('\' + 'dir\FileX.exe', 'C:\absadsaddir\FileX.exe') = False
Delphi-Quellcode:
FileNamenArray := TDirectory.GetFiles('C:\dir', '*.*', TSearchOption.soAllDirectories,
  procedure (const Path: string; const SearchRec: TSearchRec): Boolean
  begin
    // SearchRec.Name = nur der Dateiname
    // TPath.Combine(Path, SearchRec.Name) = vollsändiger Pfad
    Result := True wenn Pfad im ergebnis sein soll.
    // es geht auch Result := False; und selbst irgendwo in einer externen Liste speichern oder direkt verarbeiten
  end);

DieDolly 24. Aug 2023 15:45

AW: Dateiliste gefiltert erstellen
 
Zitat:

EndsText('FileX.exe', 'C:\dir\absadsadFileX.exe') = True
EndsText kann ich nicht nehmen, weil ein FileX.exe in der Filterliste gilt nur im Hauptverzeichnis, nirgendwoanders.

Der Teilstring ist kein Problem. Ich kann das Hauptverzeichnis einfach vorne dranhängen!

DieDolly 24. Aug 2023 16:48

AW: Dateiliste gefiltert erstellen
 
Ich stelle mir gerade die Frage, ob es nicht eigentlich schneller wäre die Dateiliste einfach zu erzeugen ohne irgendwas rauszufiltern.
Kann man dann beide Listen miteinander vergleichen und Einträge aus Dateiliste löschen die in Filterliste vorhanden sind, ohne jeden Eintrag von beiden Listen miteinander zu vergleichen?

Beispiel:
Dateiliste (existierende Dateien):
C:\File1.exe
C:\File2.exe
C:\File3.exe
C:\Sub1\Sub2\File1.exe
C:\FileX.exe
C:\Sub1\FileY.exe
C:\File4.exe
C:\File5.exe

Filterliste (auf Dateiliste anwenden):
C:\Sub1\Sub2\File1.exe
C:\FileX.exe
C:\Sub1\FileY.exe

Am Ende dürfte also nur übrig bleiben:
C:\File1.exe
C:\File2.exe
C:\File3.exe
C:\File4.exe
C:\File5.exe

tomkupitz 24. Aug 2023 16:49

AW: Dateiliste gefiltert erstellen
 
Hallo,

bau dir eine einfache HashListe mit HashItems (mit Key=Dateiname und Path-Eigenschaft im HashItem). Der Vergleich letztendlich geht dann super schnell.

Beste Grüße

DieDolly 24. Aug 2023 16:53

AW: Dateiliste gefiltert erstellen
 
Ich kann das System nicht mehr umstellen. Eine neue Liste kann ich erstellen weil ich dann wochenlang beschäftigt wäre alles abzuändern.

Die Listen sind nicht das Problem, das Erstellen ist superschnell. Das vergleichen dauert ewig, deswegen meine Idee oben. Bitte durchlesen.

tomkupitz 24. Aug 2023 17:00

AW: Dateiliste gefiltert erstellen
 
Ok, wie findest du File1.exe von Liste1 in Liste2 ?

DieDolly 24. Aug 2023 17:09

AW: Dateiliste gefiltert erstellen
 
Anders erklärt.

Die Dateiliste A wird von Winapi.Windows.FindFirstFileEx() erstellt. Das sind alle Dateien in einem Verzeichnis.
Filterliste B sind ein paar Einträge von Dateien, die am Ende nicht in A landen sollen.

Das funktioniert ja alles schon, aber ist langsam. Weil jeder Fund von Winapi.Windows.FindFirstFileEx() iteriert die komplette Liste B durch.

Meine Idee wäre jetzt, die Dateiliste A erstmal ohne Filterung komplett zu erstellen und erst danach A und B zu vergleichen.

Alles aus B soll dann aus A verschwinden.

Fast vergessen. Da die Liste A Objekte enthält, muss ich da nicht zwangsläufig Einträge rauslöschen. Man könnte auch einfach eine Flag setzen, sodass die im späteren Verlauf ignoriert werden. Das würde der vorhandene Code zulassen.

Zusammengefasst:
beide Listen existieren, das Zusammenstellen der Listen ist rasendschnell und schnell genug.
Es hapert nur beim Vegleich.

Weil Wenn Liste A 15.000 Einträge hat und B 1000, sind das, wenn man jeden Eintrag mit jedem vergleicht, sehr viele Vergleiche, viele davon mehr als unnötig.


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:16 Uhr.
Seite 1 von 2  1 2      

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