![]() |
Schnelle Dateisuche
Hallo zusammen,
ich verwende schon lange folgenden Code um nach Dateien zu suchen.
Delphi-Quellcode:
Über den Übergabeparameter bAll kann ich die Suche abbrechen, sobald ich die Datei gefunden habe. In meinem Beispiel,
function TuFiles.GetAllFiles(var slFiles:TStringlist; sFile:string; bAll, bAllVerz, bNoBAK:Boolean):LongInt;
{++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++} { GetAllFiles } {------------------------------------------------------------------------} { Erstellung : 7. 8.97 } { Letzte Änderung : 21. 4.03 } {------------------------------------------------------------------------} { Sucht ab dem übergebenen Verzeichnis in allen eventuellen Unterverzei- } { chnissen nach Dateien, die mit der übergebenen übereinstimmen. } {------------------------------------------------------------------------} { Übergabeparameter } { slFiles = Enthält die gefundenen Dateien } { sFile = Gibt vor, welche Dateien ab welchem Verzeichnis gesucht } { werden } { bAll = Legt fest, ob alle Dateien gelistet werden } { true = es werden alle Dateien gelistet } { false = sobald eine Datei gefunden wurde, die mit sFile } { übereinstimmt, wird die Suche beendet } { bAllVerz = Legt fest, in welchen Verzeichnissen gesucht wird } { true = es werden auch alle Unterverzeichnisse durchsucht } { false = es wird nur das übergebene Verzeichnis durchsucht } { bNoBAK = Legt fest, ob auch Sicherungsdateien gelistet werden } { true = Sicherungsdateien werden nicht gelistet } { false = Sicherungsdateien werden gelistet } {++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++} var Search: TSearchRec; begin // Application.ProcessMessages; // if bAbort then Exit; // Panel2.Caption:=format(' Dokument wird in %s gesucht',[ExtractFilePath(sFile)]); // Panel2.Refresh; { alle Dateien suchen } if SysUtils.FindFirst(sFile, $23, Search)= 0 then repeat if not (bNoBak) or ((bNoBAK) and not (BakDatei(Search.Name))) then slFiles.add(UpperCase(ExtractFilePath(sFile)+Search.Name)); until (SysUtils.FindNext(Search)<>0) or ((slFiles.Count>0) and not (bAll)); {$IFDEF Win32} SysUtils.FindClose(Search); {$ENDIF} if ((bAllVerz) and ((slFiles.Count=0) or ((slFiles.Count>0) and bAll))) then begin { Unterverzeichnisse durchsuchen } if (SysUtils.FindFirst(ExtractFilePath(sFile) + '*.*',fadirectory, Search)= 0) then begin repeat if((search.attr and fadirectory)=fadirectory)and(search.name[1]<>'.') then GetAllFiles(slFiles, ExtractFilePath(sFile)+ Search.Name + '\' + ExtractFileName(sFile),bAll, bAllVerz, bNoBAK); until SysUtils.FindNext(Search) <> 0; end; {$IFDEF Win32} SysUtils.FindClose(Search); {$ENDIF} end; Result:=slFiles.Count; end;
Delphi-Quellcode:
in dem die Datei in dem Unterverzeichnis "E:\Eigene Bilder\Privat\Digital\U Urlaub\2003 Kroatien" gefunden wird, benötigt die Suche 2.85sec. Führe ich nun dieselbe Suche vom selben Startverzeichnis mit dem Dateimanager 'Total Commander' (s.
procedure TForm1.Button1Click(Sender: TObject);
var slFiles : TStringlist; begin if slFiles=nil then slFiles := TStringList.Create; uHilfs1.SetStart1; if uFiles.GetAllFiles(slFiles, 'E:\Eigene Bilder\Privat\U-2003-05-31ac.jpg', false, true, true)>0 then ShowMessage(slFiles[0]+' in '+uHilfs1.GetDeltaTime1+' gefunden') else ShowMessage('Keine Datei in '+uHilfs1.GetDeltaTime1+' gefunden'); end; ![]() Danke für ein paar Tips Gerd |
Re: Schnelle Dateisuche
Kannst ja mal das hier aus der Codelib versuchen, das geht imho recht schnell...
![]() |
Re: Schnelle Dateisuche
Was macht denn die Funktion BakDatei()
Wenn die bloed implementiert ist And bNoBak then (DAUER!) |
Re: Schnelle Dateisuche
Meine Variante benoetigt 1 Sekunde bei mir fuer eine suche nach einer bestimmten Datei
wohingegen Deine Variante 71 Sekunden benoetigt und die Datei nicht findet. Du hast also mehr als nur ein Problem mit der Performance.
Delphi-Quellcode:
function Tfrm_Main.GetAllFilesFast(var slFiles:TStringlist; sPath,sFile:string; bAll, bAllVerz, bNoBAK:Boolean):longint;
var sr : TSearchRec; iRes : integer; begin iRes:=SysUtils.FindFirst(sPath+'*.*', $FF, sr); while iRes=0 do begin if sr.Attr and faDirectory >0 then begin if (sr.name[1]<>'.' ) and ballVerz then GetAllFilesFast(slFiles,sPath+sr.name+#92,sfile,ball,bAllVerz, bNoBAK); end else begin if sr.name=sFile then slFiles.add(sPath+sr.name); end; iRes:=SysUtils.FindNext(sr); end; end; |
Re: Schnelle Dateisuche
Hallo zusammen,
das ging ja rasend schnell. Die Funktion BakDatei prüft nur die Dateiendungen. Ich habe sie auskommentiert und es wurde nicht schneller. Aufgefallen ist mir aber, dass beim zweiten Suchen alles viel schneller (0.18 sec) läuft. Auch wenn sich der eigentliche Dateiname ändert. Daraufhin habe ich den Rechner runtergefahren und zuerst mit Total Commander gesucht und siehe da, jetzt lag die Suchzeit auch im 3 Sekundenbereich. Die Suchergebnisse werden also anscheinend von Windows gepuffert und beide Programme greifen beim wiederholten Suchen auf diesen Puffer zu. Meine Frage ist also beantwortet. Oder doch nicht? Gerade kam der zweite Beitrag von mashutu rein. Und nun die Frage an dich: Hast du zuerst meine und dann deinen Algorithmus getestet? Werde es bei mir auch noch testen. Auch wenn das Neustarten des PC's nervt. Danke noch mal Gerd |
Re: Schnelle Dateisuche
Auf jeden Fall solltest Du mal nach dem Fehler suchen.
Ich habe nach einer Datei gesucht die im __history Ordner meines Quelltextpfades liegt.... Die wird mit Deiner Methode nicht gefunden. das Verzeichnis wird auch nicht durchsucht... |
Re: Schnelle Dateisuche
Etwas schneller dürfte es nur noch mit den direkten Windows-Funktionen gehen:
- Windows.FindFirstFile() bzw. für die Unicode-Variante - Windows.FindFirstFileW() ![]() |
Re: Schnelle Dateisuche
Hi!
Du hast in deiner Suchfunktion 2 Suchen, d.h. du rufst 2 mal FindFirst mit allem, was dazugehört, auf. Ich hatte ein ähnliches Problem: Innerhalb einer FindFirst Suche habe ich GetSizeOfFile (oder so ähnlich) von der JCL benutzt - Diese Funktion hat auch ein FindFirst gemacht, was den Ablauf der Suche insgesamt verlangsamte. Klar, das war sowieso überflüssig, wegen TSearchRec.Size. Nach der Änderung ging alles schneller. Versuch doch mal, in der Funktion GetAllFiles nur eine Schleife mit FindFirst einzubauen. Da holst du dir dann einfach alles was gefunden wird, Unterordner schickst du direkt wieder an GetAllFiles oder merkst sie dir in einer Liste und gehst sie am Ende alle durch. Wenn ich mich recht erinnere, hat das Einlesen einer gesamten Partition vorher 120 Sekunden gedauert, nach der Änderung lag es bei 80 Sekunden. HTH. |
Re: Schnelle Dateisuche
Hallo Mashutu,
dass ich deine Datei nicht finde, liegt wahrscheinlich am Attribut $23. Ich habe aber auch deine Routine ausprobiert und seltsamerweise ist sie langsamer. Zwischen den Tests habe ich den Rechner jedes mal neu gestartet. 2x mit deiner Routine (20.87 und 20.97 sec), meine Routine mit der Abfrage BakDatei dauterte es 4.74 und 4.72 sec und so lange dauert es auch mit Total Commander nach Neustart. Die BakDatei-Abrage ist
Delphi-Quellcode:
Hallo Wicht,
function TuFiles.BakDatei(sDateiName:String):Boolean;
{++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++} { BakDatei } {------------------------------------------------------------------------} { Erstellung : 16. 7.97 } { Letzte Änderung : 16. 7.97 } {------------------------------------------------------------------------} { Stellt fest, ob die übergebene Datei eine Sicherungsdatei ist. } {++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++} var sExt : String[4]; begin sDateiName:=UpperCase(sDateiName); sExt:=ExtractFileExt(sDateiName); Result:=(Pos('~',sDateiName)>0) or { Sicherungsdateien erkennen } (sDateiName='ACA_CDM.DAT') or (Pos('$',sDateiName)>0) or (sExt = '.BAK') or (sExt = '.SIK') or (sExt = '.ERR') or (sExt = '.TMP'); end; dass ich Findfirst 2x aufrufe liegt daran, dass ich zuerst nach der Datei im aktuellen Verzeichnis suche. Wenn ich sie dort nicht finde, oder wenn ich schauen will, ob sie auch noch in anderen Unterverzeichnissen vorkommt, zweige ich mit dem nächsten FindFirst-Aufruf in die Untervezeichnise ab. Danke für die Tips Gerd |
Re: Schnelle Dateisuche
Dass das aber dann doppelt so lange dauert (so kam es mir bei meinen Versuchen jedenfalls vor) ist aber schon klar, oder?
Du lässt zweimal FindFirst für dich Filtern - besser wäre ein Aufruf, wo du selbst Filterst. Ich würde einfach ein faAnyFile benutzen in einem Durchgang, und dann prüfen, ob es eine Datei ist, oder ein Verzeichnis. In etwa so (lieblos hingeklatscht):
Delphi-Quellcode:
procedure FindStuff(Dir: string);
var Search: TSearchRec; IsFound: Boolean; i: Integer; Dirs: TStringList; begin Dirs := TStringList.Create; try IsFound := FindFirst(Dir + '*.*', faAnyFile, Search) = 0; while IsFound do begin if (Search.Name <> '.') and (Search.Name <> '..') and (not ((Search.Attr and faDirectory) = faDirectory)) then begin // Wir haben eine Datei gefunden! end; if ((Search.Attr and faDirectory) = faDirectory) and (Search.Name <> '.') and (Search.Name <> '..') then begin // Ein Verzeichnis. Dirs.Add(Dir + Search.Name); end; IsFound := FindNext(Search) = 0; end; finally Dirs.Free; end; for i := 0 to Dirs.Count - 1 do FindStuff(Dirs[i]); end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:38 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