2016-08-11 4 views
0

Ich schreibe ein Programm, um alle Dateien eines Typs auf einem Computer (zZ Bilddateien) zu finden, und ich benutze Tail-Rekursion, um Verzeichnisse auf diese Weise zu suchen:Probleme mit Tail-Rekursion in Dateioperationen (C#)

private void ImageSearchByDir(DirectoryInfo dir) 
{ 
    //search for images by directory, later display them with this method when I get basic search working 
    foreach (var f in dir.GetFiles()) 
    { 
     //add file info to current list 
     this.myfiles.Add(f); 
    } 

    foreach (var d in dir.GetDirectories()) 
    { 
     //recursive call to iterate through subdirectories 
     ImageSearchByDir(d); 
    } 
} 

Das Problem scheint bei der Suche nach Verzeichnissen mit großen Mengen von Dateien auftreten. Zum Beispiel habe ich einen Ordner mit ~ 700 Bildern gesucht, die in 3 Ebenen von Ordnern ohne Problem enthalten sind, aber der Versuch, meinen Desktop zu durchsuchen, stürzt das Programm ab. Ich nehme an, das hat etwas mit der Rekursion und der daraus resultierenden Stackgröße zu tun, und ich würde gerne eine elegantere Lösung implementieren, wenn möglich (ich habe mir das Trampolining angeschaut, aber ich bin mir nicht 100% sicher, dass das das beheben wird).

+1

1) Welche Art von Ausnahme tat du erhältst? 2) Wahrscheinlich genug, um nur den Dateinamen als _string_ zu sammeln, aber nicht als _FileInfo_? – Jackdaw

+1

Was Sie tun, ist Rekursion, aber nicht als Tail-Rekursion. Bei der Tail-Rekursion müssen nach dem Aufruf keine zusätzlichen Operationen in der Funktion ausgeführt werden. In Ihrem Fall muss die foreach-Schleife nach jedem rekursiven Aufruf nach weiteren Elementen suchen, wodurch diese nicht-tail-rekursiv wird. Luisos Antwort gibt einen Weg dies ohne Rekursion zu tun. –

+0

Als Antwort auf Jackdaw erhalte ich keinen Fehler, das Programm bleibt einfach in einem Ladezustand hängen (weißer Hintergrund, blaue Fenster laden den Kreis für den Cursor, wenn man darauf klickt, wird es als 'Nicht reagiert' markiert). Und Gideon, Sie machen einen guten Punkt, Entschuldigung, wenn meine Formulierung irreführend war. – Antidiscrete

Antwort

2

könnten Sie ein Queue verwenden und tun Sie Ihre Arbeit wie folgt aus:

class ImageSearcher 
{ 
    private Queue<DirectoryInfo> found = new Queue<...>(); 

    public void ImageSearchByDir(DirectoryInfo dir) 
    { 
     found.Enqueue(dir); 
     RealSearch(); 
    } 

    private void RealSearch() 
    { 
     while(found.Count > 0) 
     { 
      var current = found.Dequeue() 

      // do your filtering on the current folder 

      // then add the children directories 
      foreach(dir in current.GetDirectories()) 
      { 
       found.Enqueue(dir); 
      } 
     } 
    } 
} 

diese Weise können Sie Rekursion nicht haben, wenn es das ist, was denken Sie, ist beunruhigend Sie

+0

Vielen Dank, ich werde es versuchen und Sie bald aktualisieren. – Antidiscrete

+0

Gute Nachrichten: Ihre Lösung passt nahtlos in meinen vorherigen Code. Schlechte Nachrichten sind, dass ich immer noch das gleiche Problem habe, also werde ich ein bisschen mehr damit spielen. Die Verwendung einer Warteschlange scheint jedoch ein großartiger Start zu sein, und ich schätze den Vorwärtsschub. – Antidiscrete

+0

So bleibt Ihr Problem, was bedeutet, dass es nicht rekursiv war. Basierend auf @ Jackdaws Kommentar könntest du 'Queue ' haben und diese Listenordner und -dateien verwenden, indem' System.IO.Directory.EnumerateDirectories' und '..Enumerate.EnumerateFiles' verwendet werden, die beide einen' string path' nehmen. – Luiso