2016-08-11 2 views
0

Я пишу программу, чтобы найти все файлы типа на компьютере (в настоящее время файлы изображений), и я использую хвостовую рекурсию для поиска каталогов таким образом:Проблемы с хвостовой рекурсией в файловых операциях (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); 
    } 
} 

Проблема возникает при поиске каталогов с большим количеством файлов. Например, я искал папку с ~ 700 изображениями, расположенными под 3 уровнями папок, без проблем, но попытка поиска на моем рабочем столе нарушает работу программы. Я предполагаю, что это имеет какое-то отношение к рекурсии и результирующему размеру стека, и я хотел бы реализовать более элегантное решение, если это возможно (я прочитал о батуте, но я не уверен на 100%, что это исправит).

+1

1) Какое исключение сделал Вы получите? 2) Вероятно, достаточно собрать только имя файла как _string_, но не как _FileInfo_? – Jackdaw

+1

Что вы делаете, это рекурсия, но не квалифицируется как рекурсия хвоста. Рекурсия хвоста потребует, чтобы после вызова не было никаких дополнительных операций в функции. В вашем случае цикл foreach должен запускать проверку для большего количества элементов после каждого рекурсивного вызова, делая это не-хвост-рекурсивным. Ответ Луисо дает возможность сделать это без рекурсии. –

+0

В ответ на Jackdaw я не получаю ошибки, программа просто остается в состоянии загрузки (белый фон, синий стол для загрузки курсора, щелчок по нему обозначает его «Не отвечает»). И Гедеон вы делаете хороший момент, извините, если моя формулировка вводит в заблуждение. – Antidiscrete

ответ

2

Вы можете использовать Queue и делать свою работу, как это:

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); 
      } 
     } 
    } 
} 

таким образом, вы не имеете рекурсию, если это то, что вы думаете, что беспокою вас

+0

Большое спасибо, я дам вам повод и обновить вас в ближайшее время. – Antidiscrete

+0

Хорошая новость - ваше решение легко вписывается в мой предыдущий код. Плохая новость: у меня все еще такая же проблема, поэтому я собираюсь сыграть с ней немного больше. Использование очереди кажется отличным началом, хотя, и я ценю подталкивание вперед. – Antidiscrete

+0

Итак, ваша проблема остается, а это не связано с рекурсией. Основываясь на комментарии @ Jackdaw, вы можете иметь «Queue » и использовать эти папки и файлы списков с помощью 'System.IO.Directory.EnumerateDirectories' и' ..Enumerate.EnumerateFiles', которые берут «строковый путь». – Luiso

Смежные вопросы