Autor Beitrag
PachN
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 17



BeitragVerfasst: Mi 23.02.11 20:00 
Hallo zusammen,

gerade habe ich mich gefragt, ob es nicht vielleicht eine noch schnellere Möglichkeit gibt, wie ich Verzeichnisse durchsuche.

Ich mache folgendes:

Ich habe ein Array mit Dateinamen drin.
Jetzt durchsuche ich rekursiv ein Verzeichniss, nehmen wir C:\, und schau in jedem Ordner, ob hier nicht vielleicht eine Datei mit dem gesuchten Dateinamen liegt.
Wenn ja den Pfad zwischenspeichern...

Dann weiter zum nächsten Ordner und das selbe nochmal, bis eben die komplette Verzeichnisstruktur von C:\ durch ist.

Gibt es also nen schönen Algorithmus oder andere Möglichkeit das noch zu optimieren?


Ich freue mich über Vorschläge.

Grüße PachN
huuuuuh
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 665
Erhaltene Danke: 19

win xp, (win vista), win 7
VS 2008 Express Edition, VS 2010 Express Edition, VS 2010 Professionell
BeitragVerfasst: Mi 23.02.11 22:31 
in dem Fall gibt es vermutlich kaum eine performantere Lösung. bei einer iterativen Lösung wäre der Verwaltungsaufwand viel zu hoch, als dass man dadurch eine Performancesteigerung bekommen würde.
de.wikipedia.org/wik...rammierung#Effizienz
aber poste mal den Code, was optimieren könnte man vielleicht trotzdem :)
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19314
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mi 23.02.11 23:16 
user profile iconhuuuuuh hat folgendes geschrieben Zum zitierten Posting springen:
in dem Fall gibt es vermutlich kaum eine performantere Lösung. bei einer iterativen Lösung wäre der Verwaltungsaufwand viel zu hoch, als dass man dadurch eine Performancesteigerung bekommen würde.
Nein, das ist gar nicht das Problem, aber schneller würde es dennoch nicht, denn es müssen so oder so alle Verzeichnisse durchsucht werden.

Ein Problem, wenn es gar zu lange dauert, kann sein, dass der aktuelle Status auf einer GUI zu oft aktualisiert wird.

Für diese Aufgabe eignet sich auch ein Thread gut, da dann die Suche einfach im Hintergrund laufen kann.
PachN Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 17



BeitragVerfasst: Do 24.02.11 13:35 
Also hier mal der Code.
Ich habe fest gestellt, dass meine "neue" Methode, bei wenigen Ordnern sehr viel schneller ist, als meine "alte" Suchmethode.

Sind es aber sehr viele Ordner, wie oben z.B. komplett C:\, dann ist die alte Methode ca. 15% schneller.

Ich poste am besten mal beides :)

Neue Suchmethode

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
public void recursiveDirectorySearch(string pDirectory, ArrayList pSongs)
{          
  string[] arrDir;
  try
  {
    arrDir = Directory.GetDirectories(pDirectory);
  }
  catch (Exception)
  {
    //return if directory could not be read
    return;
  }

  foreach (string dir in arrDir)
  {
    try
    {
     foreach (string song in pSongs)
     {
       splitString = song.Split(new Char[] { '\\' });
       foreach (string file in Directory.GetFiles(dir, splitString[splitString.Length - 1]))
       {
          newSearchMethodList.Add(file.ToString());                  
       }
     }
    }
    catch (Exception)
    {
    }
    recursiveDirectorySearch(dir, pSongs);
  }
}



Alte Suchmethode

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
foreach (String title in pSongs)
{
  splitString = title.Split(new Char[] { '\\' });

  recursiveDirectorySearch(searchPath);

  //Weitere Bearbeitung ....

}



public void recursiveDirectorySearch(string pDirectory)
{
  string[] arrDir;
  try
  {
    arrDir = Directory.GetDirectories(pDirectory);
  }
  catch (Exception)
  {
    //return if directory could not be read
    return;
  }

  foreach (string dir in arrDir)
  {
    try
    {
     foreach (string file in Directory.GetFiles(dir, splitString[splitString.Length - 1]))
      {
        _results.Add(file.ToString());
      }
    }
    catch (Exception)
    {
    }
    recursiveDirectorySearch(dir);
 }
}




Falls es durch den Code nicht so klar rüber kommt was der unterschied ist:

In der neuen Mehtode durchsuche ich für jeden Ordner in meiner Verzeichnissstuktur einmal mein komplettes Array, ob eine oder mehrere Dateien des Arrays im aktuellen Ordner sind.

In der alten Methode nehme ich mir zuerst ein Arrayelement und durchsuche dann die komplette Verzeichnisstruktur nach diesem Element. Wenn ich dann einmal durch bin,
nehme ich mir das nächste Element und durchsuche wieder die komplette Struktur usw.

Fragt mich nicht warum, aber die alte Methode ist bei sehr vielen Ordnern (bei meinem Test > 50000) wirklich schneller, obwohl ich n-Mal die komplette Struktur durchsuche und nicht nur 1 mal wie bei der neuen Methode.


Grüße PachN


P.S.: Suche läuft schon in eigenem Thread ;)
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Do 24.02.11 15:25 
Wie sieht es aus, wenn du beide Methoden kombinierst?
ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
      var songFileNames = new HashSet<string>();
      foreach (String title in pSongs)
      {
        songFileNames.Add(Path.GetFileName(title));
      }
      RecursiveDirectorySearch(searchPath, songFileNames);
    }

    public void RecursiveDirectorySearch(string directory, HashSet<string> songFileNames)
    {
      string[] subdirs;
      try
      {
        subdirs = Directory.GetDirectories(directory);
      }
      catch (Exception)
      {
        //return if directory could not be read
        return;
      }

      foreach (string dir in subdirs)
      {
        try
        {
          foreach (string file in Directory.GetFiles(dir))
          {
            if (songFileNames.Contains(file))
            {
              newSearchMethodList.Add(file);
            }
          }
        }
        catch (Exception)
        {
        }
        RecursiveDirectorySearch(dir, songFileNames);
      }
    }

Habe mir mal erlaubt, deinen Code etwas an die Standards anzugleichen ;) .

_________________
>λ=
PachN Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 17



BeitragVerfasst: Do 24.02.11 15:49 
Hallo,

ja ist bisschen "quick'n'dirty" aber sollte doch mal anfangen aufzuräumen, wird doch etwas komplexer das alles.

Für die ein oder anderen Methoden die du da verwendet hast bedank ich mich schon mal.
Das .NET Framework ist ja auch so riesig, wenn man da nicht weiß, dass es sowas schon gibt und vorallem wo, dann macht man es halt so wie ich^^

Aber was meinst du mit beide kombinieren?
Steh grade bisschen auf dem Schlauch. Kann mir da gerade nichts drunter vorstellen.

Grüße PachN



EDIT :shock: Oh hab ja garnicht gesehen, dass du schon was angepasst hast. Ich werd es mal versuchen. Danke.
PachN Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 17



BeitragVerfasst: Do 24.02.11 16:26 
Hm dauert leider genauso lange.

Dann werd ich wohl ne Abfrage einbauen, nach der das Programm selbst aufgrund der zu überprüfenden Datenmenge entscheidet, welche Methode es nimmt.

Totzdem danke. Deine Verbesserungen hab ich ja übernommen :)

Grüße PachN
PachN Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 17



BeitragVerfasst: Do 24.02.11 19:04 
Oh man...
Hab auf meiner GUI nur so ne Stausbar.
Aber die bremst alles sowas von aus.
Mit aktualiesieren der Bar = 6 Minuten 42 Sekunden...

Ohne aktualisieren = 11 Sekunden -_-
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19314
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Do 24.02.11 19:49 
Wie ich ja auch geschrieben habe... ;-)
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Ein Problem, wenn es gar zu lange dauert, kann sein, dass der aktuelle Status auf einer GUI zu oft aktualisiert wird.