![]() |
ListFiles mit FindFirst beschleunigen
Hallo zusammen,
ich habe bei meiner Applikation mittlerweile festgestellt, dass die Routine zum Auflisten bestimmter Dateien in einem Verzeichnis bei knapp 3500 Dateien ca. 15 Sekunden dauert. Ich suche mit folgender Routine das Verzeichnis ab:
Delphi-Quellcode:
Sind die Kriterien erfüllt worden, wird dann außerhalb dieser Routine weiter mit den einzelnen Dateien gearbeitet.
procedure ListFiles(Path, Ext: string; FileList: TStringList; Attr: integer);
var SR : TSearchRec; begin if Length(Path) > 0 then Path := IncludeTrailingBackslash(Path); if FindFirst(Path + Ext, faAnyFile, SR) = 0 then begin repeat if (SR.Attr <> faDirectory) then begin if (fmPhoto.ImageSet.CheckAttr) and (not fmPhoto.DoRefreshAll) then if (SR.Attr and Attr) = 0 then Continue; if UpperCase(ExtractFileExt(SR.Name)) = UpperCase(ExtractFileExt(Ext)) then FileList.Add(SR.Name); end; until FindNext(SR) <> 0; SysUtils.FindClose(SR); end; end; Wie kann man also diese Routine optimieren bzw. beschleunigen? Danke & Gruß, Moony |
Re: ListFiles mit FindFirst beschleunigen
FindFirst ist von Haus aus langsam. (einzige Lösung wäre die MFT direkt auszulesen, aber das ist nicht unbedingt so einfach)
Was du aber machen kannst (es kommt darauf an, was sich hinter der Stringliste versteckt), wäre deren Updaten per ![]() |
Re: ListFiles mit FindFirst beschleunigen
Z.B.
Delphi-Quellcode:
nur einmal am Anfang der Funktion machen.
UpperCase(ExtractFileExt(Ext))
Und da wir nicht wissen was
Delphi-Quellcode:
ist evtl. das die Bremse (Profiler würde helfen)
(fmPhoto.ImageSet.CheckAttr) and (not fmPhoto.DoRefreshAll)
|
Re: ListFiles mit FindFirst beschleunigen
Oh, sorry.
Das
Delphi-Quellcode:
sind Boolean-Variablen einfach nur um zu prüfen ob ich alle Dateien mit der Endung nehmen soll oder nur die mit der angegebenem Attribut.
(fmPhoto.ImageSet.CheckAttr) and (not fmPhoto.DoRefreshAll)
Das Uppercase nur einmal aufzurufen hat keine Verbesserung gebracht. @himitsu: Die Stringliste wird leer übergeben und in dieser Routine ggf. gefüllt, damit ich weiter mit den benötigten Dateien arbeiten kann. Wie kann ich das denn mit MFT lösen bzw. in wie weit hilft mir BeginUpdate weiter? Gruß |
Re: ListFiles mit FindFirst beschleunigen
Hallo,
wo suchst du die Dateien? Lokal auf der Festplatte oder im Netzwerk? Welches Betriebssystem verwendest du? Wenn du mehrfach im selben Verzeichnis suchst, ändert sich die Zeit? Befinden sich andere Dateien in dem Verzeichnis, die die Suchkriterien nicht erfüllen (z.B. andere Dateiendung) Das sind so die Kriterien, nach den ich diese Suchalgorithmen angepackt habe. Aber es ist tatsächlich so, dass es Situationen gibt, bei denen man nicht schneller werden kannst. Selbst MS versucht dieses Problem an zu gehen durch Indizierung der Dateien oder andere File-Systeme die eine Suche ermöglichen. Aber das hilft dir ja erstmal nicht weiter. Greez, Chris |
Re: ListFiles mit FindFirst beschleunigen
Also, die Dateisuche findet fast immer über ein lokales Netzwerk statt. In den Verzeichnissen sind fast immer nur die Dateien drin, welche die gesuchte Endung besitzen, ist aber keine Sicherheit dass es so ist. Es sind ebenfalls Dateien im Verzeichnis, welche die Suchkriterien nicht erfüllen. Es kommt also auch mal vor, dass ein Verzeichnis durchlaufen wird, aber keine zutreffende Datei gefunden wird.
|
Re: ListFiles mit FindFirst beschleunigen
Hallo Moony,
Über das Netzwerk ist es tatsächlich so, dass die Zeiten deutlich länger sind als auf Lokalen Festplatten des Rechners. Deinen Algo würde ich erstmal so anpassen wie auch schon von anderen vorgeschlagen:
Delphi-Quellcode:
Wobei ich nicht ganz verstehe, wie du die MEthode aufrufst. Bei mir würde meine Version so aussehen:
procedure ListFiles(Path, Ext: string; FileList: TStrings; Attr: integer);
var SR : TSearchRec; CheckAttrAndNotRefreshAll : Boolean; // neu begin if Length(Path) > 0 then Path := IncludeTrailingBackslash(Path); //Ext := UpperCase(Ext); // neu CheckAttrAndNotRefreshAll := (fmPhoto.ImageSet.CheckAttr) and (not fmPhoto.DoRefreshAll); // neu if FindFirst(Path + '*' + Ext, faAnyFile, SR) = 0 then // Stern eingefügt begin FileList.BeginUpdate; try repeat if (SR.Attr and faDirectory) = 0 then begin if CheckAttrAndNotRefreshAll then begin if (SR.Attr and Attr) = 0 then Continue; end; // Brauchst du das Hier wirklich? //if UpperCase(ExtractFileExt(SR.Name)) = Ext then //begin FileList.Add(SR.Name); //end; end; until FindNext(SR) <> 0; finally FileList.Endupdate; end; SysUtils.FindClose(SR); end; end;
Delphi-Quellcode:
Somit wird auch der Vergleich auf die Variable Ext unnötig. Oder hab ich das jetzt was falsch verstanden?
Listfiles('X:\TestVieleDateien', '.jpg', ListBox1.Items, 0);
Greez, Chris [EDIT]Quelltext angepasst wegen Beitrag #9, #11, #13. Danke DeddyH und himitsu[/EDIT] |
Re: ListFiles mit FindFirst beschleunigen
MFT (MasterFileTable) ist 'ne Kontrollstruktur innerhalb einer NTFS-Partition ... kann man also nur nutzen, wenn man direkten Zugriff auf dieses Laufwerk hätte ... also im Netzwerk geht sowas nicht.
Wenn noch andere Dateien im Verzeichnis vorhanden sind, neben jenen, welche deiner gesuchten "Dateierweiterung" (EXT), dann könnte es schon was bringen, wenn man nicht erstmal alles sucht und danach filtert. Die einzige Möglichkeit, welche danach noch eine Beschleunigung bringen würde, wäre das Verzeichnis lokal auszulesen und sich die Liste komplett über's Netzwerk zu schicken. Also ein Programm auf der anderen Netzwerkseite, welche das direkt ausließt und alles zusammen in einem Datenstrom zu deinem Programm schickt. |
Re: ListFiles mit FindFirst beschleunigen
Bissel OT: Ich frage mich die ganze Zeit, ob diese Zeile wirklich richtig ist:
Zitat:
|
Re: ListFiles mit FindFirst beschleunigen
Zitat:
Delphi-Quellcode:
Da stimme ich dir zu.
if (SR.Attr and faDirectory) <> faDirectory then
Greez, Chris |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:58 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