AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

Directory und Files auflisten

Ein Thema von Smiley · begonnen am 12. Aug 2019 · letzter Beitrag vom 17. Aug 2019
Antwort Antwort
Seite 1 von 2  1 2   
Benutzerbild von Smiley
Smiley

Registriert seit: 9. Dez 2004
Ort: Gedern
205 Beiträge
 
Delphi 10.4 Sydney
 
#1

Directory und Files auflisten

  Alt 12. Aug 2019, 17:49
Hallo Delphi Freunde

ich bin Hobbyprogrammierer und liebe Delphi, manchmal fehlt mir aber die Erfahrung, da ich nicht so oft etwas programmiere.

Im Moment will ich mir eine Liste von Verzeichnissen und Dateien einlesen und später in eine Datenbank schreiben um die Dateien besser suchen, sortieren und kategorisieren zu können.
Zur Zeit habe ich erstmal eine Listbox für die Haupverzeichnisse und ein Grid zum anzeigen der Pfade und Dateinamen angelegt.
Ich benutze Delphi Rio 3.2 und die TMS Komponenten wenn nötig.
Einerseits soll das Einlesen der Dateinamen möglichst effektiv und schnell funktionieren, andererseits will ich aber auch nicht immer wieder das Rad neu erfinden.
Als erstes habe ich mal den Befehl TDirectory.GetDirectories benutzt um die Verzeichnisse einzulesen.
Bei normalen Verzeichnissen flutscht das auch recht gut.
Eine Verzeichnis hat jedoch etwa 14000 Unter-Verzeichnisse und 480000 Dateien, da dauert das einlesen knapp 2 Minuten.
Ich hatte schon überlegt die einzelen Hautverzeichnisse in verschiedenen Threads durchsuchen zu lassen, da das Formular mit "keine Rückmeldung" einige Zeit einfriert, bis dieses große Verz. gelesen worden ist.

1. Bringt es überhaupt etwas mit mehreren Tasks die Verz. gleichzeitig durchsuchen zu lassen ? (Dateien liegen auf einem NAS mit normaler Festplatte)
2. Gibt es einen Befehl der die Größe eines Verzeichnises anzeigt ohne das ganze Verz. zu durchsuchen ? (Um festzustellen wo es sich lohnt zu optimieren)
3. Sind selbstgeschriebene Routinen mit FindFirst,FindNext schneller ?
4. Gibt es auch eine TMS-Komponente die das machen kann, ohne was anzuzeigen wie TAdvTreeView oder TAdvDirectoryList und sind die schneller als GetDirectory ?

Hier etwas Code den ich dazu geschrieben habe:

Delphi-Quellcode:
procedure TForm1.btnStartClick(Sender: TObject);
var
  // SearchResult
  MainVerz: TStringDynArray;
  I: Integer;
  // var i:Integer;
  SearchResult: TStringDynArray;
  StartTime: TTime;
begin
  Grid.RowCount := 1000; // High(SearchResult);
  Grid.FixedCols := 1;
  Grid.ColCount := 3;
  Grid.StartUpdate;
  AktLine := 1;

  // Alle Hauptverzeichnisse einlesen und dann pro Verz. eine Suche ausführen in eigenem Thread
  MainVerz := TDirectory.GetDirectories('Y:\Dateien\', TSearchOption.soTopDirectoryOnly, nil);

  for j := 0 to High(MainVerz) do
  begin
    ListBox1.Items.Add(MainVerz[j]);
    try
      Begin
        // Einlesen der Dateien ab dem Verz[j]
        StartTime := Now();
        SearchResult := TDirectory.GetFiles(MainVerz[j], '*.pdf', TSearchOption.soAllDirectories);
        for I := Low(SearchResult) to High(SearchResult) do
        begin
          if SearchResult[I] <> 'then
          begin
            Grid.Cells[1, AktLine] := ExtractFilename(SearchResult[I]);
            Grid.Cells[2, AktLine] := ExtractFilePath(SearchResult[I]);
            inc(AktLine);
          end;
        end;
        TaskStatus[j] := True;
        ListBox1.Items.Add(' Zeit: ' + TimeToStr(Now - StartTime));
        // Application.ProcessMessages;
      End;
    except
      { Catch the possible exceptions }
      MessageDlg('Incorrect path or search mask', mtError, [mbOK], 0);
      Exit;
    end;

  end;

  Grid.RowCount := AktLine;
  Grid.AutoSizeCol(1);
  Grid.AutoSizeCol(2);
  Grid.SortSettings.IgnoreCase := True;
  Grid.Sort(1, sdAscending);
  Grid.SortSettings.Show := True;
  Grid.EndUpdate;
end;
In der "for I := Low(SearchResult) to High(SearchResult) do" Schleife soll später noch mehr ausgewertet werden (Datum,Dateigröße usw.)
Abwägen zwischen Geschwindigkeit und Einfachheit.
Wenn es bei 2 Minuten Dauer 10 Sekunden mehr oder weniger sind ist das nicht viel, aber den Minutenbereich möchte ich schon umgehen wenn möglich.
Wenn schon mit threads gearbeitet werden muss dachte ich an "OmniThreadLibrary".
Ein Thread ist ja nicht schlimm aber mehrere, damit es sich auch lohnt (CPU Cores ausnutzen) das ist ohne die Lib schon schwierig, wie ich festgestellt habe.

Geändert von Smiley (12. Aug 2019 um 17:52 Uhr) Grund: schreibfehler entdeckt
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#2

AW: Directory und Files auflisten

  Alt 12. Aug 2019, 18:07
Bei Festplattenzugriffen sind mehrere Threads nicht immer sinnvoll, da die Schreib- und Leseköpfe ja auch nur an einer Stelle sein können. Im Gegenteil, mehrere Threads können dazu führen, dass sie unnötig oft hin und her springen müssen, was der Performance dann eher abträglich ist.

Aber eine Forensuche nach zum Beispiel FindFirstFile und ähnlichen sollte genügen Material zu Tage fördern.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.659 Beiträge
 
FreePascal / Lazarus
 
#3

AW: Directory und Files auflisten

  Alt 12. Aug 2019, 18:14
Es gibt/gab Festplatten die eine sog. verschränkte Suche beherrschen. Bei denen könnte es etwas bringen mit mehreren Threads die Platte zu bearbeiten. Was auf jeden Fall empfehlenswert ist, die Plattenzugriffe und die Anzeige per Thread voneinander zu trennen. Und für den Aufbau der angezeigten Daten mit BeginUpdate/EndUpdate arbeiten, sofern das unterstützt wird.

Gruß
K-H
Programme gehorchen nicht Deinen Absichten sondern Deinen Anweisungen
R.E.D retired error detector
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#4

AW: Directory und Files auflisten

  Alt 12. Aug 2019, 18:34
Und bei SSDs wäre es egal. Da würde ich dann auf die zusätzliche Komplexität mit mehreren Threads verzichten. Ergo: Ein zusätzlicher Thread, um die Aufgabe von der GUI zu trennen. Und den Programmcode innerhalb dieses Threads optimieren. Wobei, ein 5-Minuten-Ei wird man nie in 3 Minuten gekocht bekommen.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.536 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: Directory und Files auflisten

  Alt 12. Aug 2019, 19:01
[OT] Aber du willst es doch immer 4 1/2 Minuten gekocht haben. Vielleicht stimmt mit deinem Gefühl etwas nicht. [/OT]
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Benutzerbild von Smiley
Smiley

Registriert seit: 9. Dez 2004
Ort: Gedern
205 Beiträge
 
Delphi 10.4 Sydney
 
#6

AW: Directory und Files auflisten

  Alt 12. Aug 2019, 19:16
Gut gebrüllt Löwe DeddyH, Loriot ist immer noch gut.

Dass es andere Verfahren zum einlesen gibt weiß ich, deshalb meine Frage, was bringen die anderen Lösungen ?
Ist FindFirstFile schneller als .GetDirectories ?
  Mit Zitat antworten Zitat
gast2019
(Gast)

n/a Beiträge
 
#7

AW: Directory und Files auflisten

  Alt 12. Aug 2019, 22:46
Zitat:
Dass es andere Verfahren zum einlesen gibt weiß ich, deshalb meine Frage, was bringen die anderen Lösungen ?
Vermutlich bringen die anderen Lösungen nur eine andere/einfachere Syntax für "neuere" Delphi-Versionen. Mit weniger Lametta

In #3 und #4 wurde IHMO das Wesentliche bereits geschrieben.
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#8

AW: Directory und Files auflisten

  Alt 12. Aug 2019, 23:02
[OT] Aber du willst es doch immer 4 1/2 Minuten gekocht haben. Vielleicht stimmt mit deinem Gefühl etwas nicht. [/OT]
"Mach doch mal was. Liste doch mal Dateien auf!"

So. Jetzt aber bitte zurück zum Thema.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Benutzerbild von Smiley
Smiley

Registriert seit: 9. Dez 2004
Ort: Gedern
205 Beiträge
 
Delphi 10.4 Sydney
 
#9

AW: Directory und Files auflisten

  Alt 16. Aug 2019, 16:34
Ich habe jetzt mal ausprobiert was es ausmacht mit 4 Threads zu arbeiten.
Habe die Omnithread Lib benutzt und damit mein großes Verzeichnis eingelesen.
14019 Verzeichnisse 48488 Dateien

Mit OmniThread Zeit: 01:46:370
Ohne Threads Zeit: 01:56:908

Der Unterschied ist also kaum spürbar, zumindest wenn die Suche über ein Netzwerklaufwerk läuft.
  Mit Zitat antworten Zitat
Benutzerbild von Smiley
Smiley

Registriert seit: 9. Dez 2004
Ort: Gedern
205 Beiträge
 
Delphi 10.4 Sydney
 
#10

AW: Directory und Files auflisten

  Alt 16. Aug 2019, 16:39
Eine andere Sache ist hierbei aufgetreten.
Möglicherweise hat dazu jemand eine Idee.

Wenn ich in mein Programm ein Application.ProcessMessages einbaue, hängt das Programm an dieser Stelle und muss mit dem Taskmanager beendet werden.

Hier das Programm dazu:

Delphi-Quellcode:
// **************************************************************************
procedure TForm1.btnStartClick(Sender: TObject);
var
  // SearchResult
  MainVerz: TStringDynArray;
  SearchResult: TStringDynArray;
  StartTime, FirstTime: TTime;
  I: Integer;

begin
  for I := 0 to 10 do
    TaskStatus[I] := False;

  Grid.RowCount := 1000; // High(SearchResult);
  Grid.FixedCols := 1;
  Grid.ColCount := 3;
  Grid.StartUpdate;
  AktLine := 1;

  // Uses IOUtils für GetDir..und System.Types für DynArray hinzufügen
  // Alle Hauptverzeichnisse einlesen und dann pro Verz. eine Suche ausführen in eigenem Thrad
  StartTime := Now();
  FirstTime := Now;
  MainVerz := TDirectory.GetDirectories('Y:\eBooks\eLoad24', TSearchOption.soTopDirectoryOnly, nil);

  for j := 0 to High(MainVerz) do
    begin
      ListBox1.Items.Add(MainVerz[j]);
      try
        Begin
          // Einlesen der Dateien ab dem Verz[j]
          SearchResult := TDirectory.GetFiles(MainVerz[j], '*.pdf', TSearchOption.soAllDirectories);
          for I := Low(SearchResult) to High(SearchResult) do
            begin
              if SearchResult[I] <> 'then
                begin
                  Grid.Cells[1, AktLine] := ExtractFilename(SearchResult[I]);
                  Grid.Cells[2, AktLine] := ExtractFilePath(SearchResult[I]);
                  inc(AktLine);
                end;
            end;
          TaskStatus[j] := True;
          ListBox1.Items.Add('Task ' + IntToStr(j) + ' Zeit: ' + FormatDateTime('hh:nn:ss:zzz', Now - StartTime));
          StartTime := Now();
          // Application.ProcessMessages;
        End;
      except
        { Catch the possible exceptions }
        MessageDlg('Incorrect path or search mask', mtError, [mbOK], 0);
        Exit;
      end;
      // Application.ProcessMessages;

    end;

  ListBox1.Items.Add('--------------------------------------------');
  ListBox1.Items.Add('Gesamt Zeit: ' + FormatDateTime('hh:nn:ss:zzz', Now - FirstTime));

  Grid.RowCount := AktLine;
  Grid.AutoSizeCol(1);
  Grid.AutoSizeCol(2);
  Grid.SortSettings.IgnoreCase := True;
  Grid.Sort(1, sdAscending);
  Grid.SortSettings.Show := True;
  Grid.EndUpdate;
end;
// **************************************************************************
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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 03:30 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