AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Schnelle Dateisuche

Ein Thema von norwegen60 · begonnen am 7. Jan 2008 · letzter Beitrag vom 9. Jan 2008
Antwort Antwort
Seite 1 von 2  1 2      
norwegen60

Registriert seit: 23. Dez 2007
Ort: Schwarzwald
505 Beiträge
 
Delphi 12 Athens
 
#1

Schnelle Dateisuche

  Alt 7. Jan 2008, 11:44
Hallo zusammen,

ich verwende schon lange folgenden Code um nach Dateien zu suchen.

Delphi-Quellcode:
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;
Über den Übergabeparameter bAll kann ich die Suche abbrechen, sobald ich die Datei gefunden habe. In meinem Beispiel,

Delphi-Quellcode:
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;
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. http://www.ghisler.com/deutsch.htm) aus, benötigt dieser nur Bruchteile einer Sekunde. Wie kann man selber eine so schnelle Suche programmieren?

Danke für ein paar Tips
Gerd
  Mit Zitat antworten Zitat
Benutzerbild von Aurelius
Aurelius

Registriert seit: 29. Jan 2007
Ort: Erfurt
753 Beiträge
 
Delphi 7 Personal
 
#2

Re: Schnelle Dateisuche

  Alt 7. Jan 2008, 11:51
Kannst ja mal das hier aus der Codelib versuchen, das geht imho recht schnell...

http://www.delphipraxis.net/internal...464&highlight=
Jonas
  Mit Zitat antworten Zitat
mashutu

Registriert seit: 15. Nov 2007
195 Beiträge
 
#3

Re: Schnelle Dateisuche

  Alt 7. Jan 2008, 12:04
Was macht denn die Funktion BakDatei()
Wenn die bloed implementiert ist And bNoBak then (DAUER!)
utu

if it was hard to write it should be hard to read
  Mit Zitat antworten Zitat
mashutu

Registriert seit: 15. Nov 2007
195 Beiträge
 
#4

Re: Schnelle Dateisuche

  Alt 7. Jan 2008, 12:58
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;
utu

if it was hard to write it should be hard to read
  Mit Zitat antworten Zitat
norwegen60

Registriert seit: 23. Dez 2007
Ort: Schwarzwald
505 Beiträge
 
Delphi 12 Athens
 
#5

Re: Schnelle Dateisuche

  Alt 7. Jan 2008, 13:02
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
  Mit Zitat antworten Zitat
mashutu

Registriert seit: 15. Nov 2007
195 Beiträge
 
#6

Re: Schnelle Dateisuche

  Alt 7. Jan 2008, 13:10
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...
utu

if it was hard to write it should be hard to read
  Mit Zitat antworten Zitat
Benutzerbild von bigg
bigg

Registriert seit: 1. Jul 2007
155 Beiträge
 
#7

Re: Schnelle Dateisuche

  Alt 7. Jan 2008, 13:53
Etwas schneller dürfte es nur noch mit den direkten Windows-Funktionen gehen:
- Windows.FindFirstFile() bzw. für die Unicode-Variante
- Windows.FindFirstFileW()

http://msdn2.microsoft.com/en-us/library/aa364418.aspx
  Mit Zitat antworten Zitat
Benutzerbild von wicht
wicht

Registriert seit: 15. Jan 2006
Ort: Das schöne Enger nahe Bielefeld
809 Beiträge
 
Delphi XE Professional
 
#8

Re: Schnelle Dateisuche

  Alt 7. Jan 2008, 14:46
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.
http://streamwriter.org

"I make hits. Not the public. I tell the DJ’s what to play. Understand?"
  Mit Zitat antworten Zitat
norwegen60

Registriert seit: 23. Dez 2007
Ort: Schwarzwald
505 Beiträge
 
Delphi 12 Athens
 
#9

Re: Schnelle Dateisuche

  Alt 7. Jan 2008, 15:15
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:
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;
Hallo Wicht,

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
  Mit Zitat antworten Zitat
Benutzerbild von wicht
wicht

Registriert seit: 15. Jan 2006
Ort: Das schöne Enger nahe Bielefeld
809 Beiträge
 
Delphi XE Professional
 
#10

Re: Schnelle Dateisuche

  Alt 7. Jan 2008, 15:52
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;
http://streamwriter.org

"I make hits. Not the public. I tell the DJ’s what to play. Understand?"
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:44 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