Возможно, вы захотите посмотреть на этот вопрос, где я представил пример кода, который использует рекурсию для визуализации структуры каталогов в TreeView. Логика должна быть одинаковой в большинстве случаев.
Cerebrus
5
Проблема в том, что он очень легко ломается, если у вас нет доступа к одному каталогу: нет результатов ...
Марк Гравелл
1
Если у вас возникают проблемы, когда некоторые файлы недоступны,
изучите
Ответы:
186
Эта статья охватывает все, что вам нужно. За исключением случаев поиска файлов и сравнения имен, просто распечатайте имена.
Это может быть изменено так:
staticvoidDirSearch(string sDir){try{foreach(string d inDirectory.GetDirectories(sDir)){foreach(string f inDirectory.GetFiles(d)){Console.WriteLine(f);}DirSearch(d);}}catch(System.Exception excpt){Console.WriteLine(excpt.Message);}}
Добавил барлоп
GONeale упоминает, что выше не перечисляет файлы в текущем каталоге и предлагает поместить часть списка файлов вне той части, которая получает каталоги. Следующее сделало бы это. Он также включает строку Writeline, которую вы можете раскомментировать, которая помогает отследить, где вы находитесь в рекурсии, что может помочь показать вызовы, чтобы показать, как работает рекурсия.
DirSearch_ex3("c:\\aaa");staticvoidDirSearch_ex3(string sDir){//Console.WriteLine("DirSearch..(" + sDir + ")");try{Console.WriteLine(sDir);foreach(string f inDirectory.GetFiles(sDir)){Console.WriteLine(f);}foreach(string d inDirectory.GetDirectories(sDir)){DirSearch_ex3(d);}}catch(System.Exception excpt){Console.WriteLine(excpt.Message);}}
Этот метод не выводит список файлов для начального каталога, только его подкаталоги и ниже. Я бы переместил GetFiles за пределы GetDirectories
GONeale
1
Иногда не нужны файлы для начального каталога, и в этом случае это идеально подходит для достаточно небольших структур. Для очень больших списков используйте что-то вроде решения Марка Гравелла: stackoverflow.com/a/929418/91189
Джозеф Габриэль
2
@ GONeale правильно. Гораздо менее правдоподобно, чтобы пользователь не ожидал списка файлов входного корневого каталога. Ввод слова является ключевым здесь. Это было введено по причине.
Флорин Мирча
2
Мне нужно было добавить пробную защелку вокруг внутреннего цикла foreach, иначе он не продолжит ошибки отказа в доступе
Shaun
3
Вам следует избегать перехвата исключения - действительно ли вы хотите перехватить исключение OutOfMemoryException, например? Только поймать то, что вы можете справиться.
alastairtree
435
Обратите внимание, что в .NET 4.0 есть (предположительно) основанные на итераторах (а не на основе массивов) файловые функции, встроенные в:
На данный момент я бы использовал что-то вроде ниже; встроенный рекурсивный метод ломается слишком легко, если у вас нет доступа к одному подкаталогу ...; Queue<string>использование позволяет избежать слишком много вызовов стеки рекурсии, и блок итератора избегает нас , имеющими огромный массива.
@soandos В точке рекурсивного повторного анализа EnumerateFiles выдает IOException «Имя файла не может быть разрешено системой»
SerG
5
Для всех, кто хочет знать, *.*включает ли также файлы без расширения: Да, это так, протестировано минуту назад.
Тобиас Кнаусс
1
Чтобы использовать это вам нужно будет добавитьusing System.IO;
Восстановить Моника - Goodbye SE
7
@Wikis и для использования Consoleвам нужно будет добавить using System;- но, поскольку IDE может добавить все необходимые usingдирективы для вас (ctrl +.), И поскольку мы не используем здесь ничего экзотического, обычно их не включают. Черт возьми, тебе тоже понадобится classопределение и т. Д. Просто скажи
Марк Гравелл
1
@MarcGravell Мы находимся в ядре .net и мире кода Visual Studio, поэтому включение операторов использования всегда приветствуется в любом примере кода .net для сохранения серии поисков и бессмысленного «бритья яка»
Как избежать ошибки, если у пользователя входа нет доступа к некоторым папкам.
Ромил Кумар Джайн
5
@Romil Я не верю, что этот фрагмент кода пытается показать полную функциональность, только необработанную функциональность, которую искал OP. Спасибо, что поделился, Пескума!
kayleeFrye_onDeck
@kayleeFrye_onDeck, я ставлю вопрос только в том случае, если при получении файлов появляется рейз для какой-либо папки. В связи с этим мы реализуем нашу собственную рекурсивную функцию.
Ромил Кумар Джейн
3
Вы получите «UnauthorizedAccessException» с этим решением. У вас должно быть решение, которое может обрабатывать подобные ошибки.
Кайран
13
В .NET 4.5, по крайней мере, есть эта версия, которая намного короче и имеет дополнительный бонус оценки любых критериев файла для включения в список:
В Framework 2.0 вы можете использовать (в нем перечислены файлы корневой папки, лучше всего самый популярный ответ):
staticvoidDirSearch(string dir){try{foreach(string f inDirectory.GetFiles(dir))Console.WriteLine(f);foreach(string d inDirectory.GetDirectories(dir)){Console.WriteLine(d);DirSearch(d);}}catch(System.Exception ex){Console.WriteLine(ex.Message);}}
Некоторые отличные ответы, но эти ответы не решили мою проблему.
Как только возникает проблема с разрешением папки: «Отказано в доступе», код завершается ошибкой. Вот что я использовал для решения проблемы «Отказано в доступе»:
/// <summary>/// Scans a folder and all of its subfolders recursively, and updates the List of files/// </summary>/// <param name="sFullPath">Full path of the folder</param>/// <param name="files">The list, where the output is expected</param>internalstaticvoidEnumerateFiles(string sFullPath,List<FileInfo> fileInfoList){try{DirectoryInfo di =newDirectoryInfo(sFullPath);FileInfo[] files = di.GetFiles();foreach(FileInfo file in files)
fileInfoList.Add(file);//Scan recursivelyDirectoryInfo[] dirs = di.GetDirectories();if(dirs ==null|| dirs.Length<1)return;foreach(DirectoryInfo dir in dirs)EnumerateFiles(dir.FullName, fileInfoList);}catch(Exception ex){Logger.Write("Exception in Helper.EnumerateFiles", ex);}}
Вы вручную делаете то, что DirectoryInfo.GetFiles () сделает для вас из коробки - просто используйте перегрузку с SearchOption.AllDirectories, и она будет восстанавливать все самостоятельно. Так что это сложное решение.
Philw
2
Я предпочитаю использовать DirectoryInfo, потому что я могу получить FileInfo, а не только строки.
@MassimilianoKraus Я бы сказал, что, хотя это и не требуется, становится понятнее, что его метод изменится, filesи вы больше не сможете просто new List<FileInfo>()указывать в качестве параметра, который был бы бесполезен. Может позволить некоторую подоптимизацию и избежать создания нового объекта, если это не требуется.
Джеромей
@JeromeJ Если вы знаете, что такое ООП, вы знаете, что всякий раз, когда вы передаете объект методу, этот метод может изменять свойства / поля объекта. Так что refничего не проясняет. refЦель «s, чтобы изменить весь filesуказатель даже для вызывающей метод: это опасная операция , и здесь нет необходимости в том , что вы можете просто заполнить список, вам не нужно повторно точки в другой список на куча refследует использовать только в очень особых случаях; В большинстве случаев вам просто нужно реализовать что-то более функционально-парадигмальное.
Массимилиано Краус
1
Чтобы избежать UnauthorizedAccessException, я использую:
var files =GetFiles(@"C:\","*.*",SearchOption.AllDirectories);foreach(var file in files){Console.WriteLine($"{file}");}publicstaticIEnumerable<string>GetFiles(string path,string searchPattern,SearchOption searchOption){var foldersToProcess =newList<string>(){
path
};while(foldersToProcess.Count>0){string folder = foldersToProcess[0];
foldersToProcess.RemoveAt(0);if(searchOption.HasFlag(SearchOption.AllDirectories)){//get subfolderstry{var subfolders =Directory.GetDirectories(folder);
foldersToProcess.AddRange(subfolders);}catch(Exception ex){//log if you're interested}}//get filesvar files =newList<string>();try{
files =Directory.GetFiles(folder, searchPattern,SearchOption.TopDirectoryOnly).ToList();}catch(Exception ex){//log if you're interested}foreach(var file in files){yieldreturn file;}}}
Если вам нужны только имена файлов, и, поскольку мне не очень нравятся большинство решений здесь (по функциональности или по удобочитаемости), как насчет этого ленивого?
privatevoidFoo(){var files =GetAllFiles("pathToADirectory");foreach(string file in files){// Use can use Path.GetFileName() or similar to extract just the filename if needed// You can break early and it won't still browse your whole disk since it's a lazy one}}/// <exception cref="T:System.IO.DirectoryNotFoundException">The specified path is invalid (for example, it is on an unmapped drive).</exception>/// <exception cref="T:System.UnauthorizedAccessException">The caller does not have the required permission.</exception>/// <exception cref="T:System.IO.IOException"><paramref name="path" /> is a file name.-or-A network error has occurred.</exception>/// <exception cref="T:System.IO.PathTooLongException">The specified path, file name, or both exceed the system-defined maximum length. For example, on Windows-based platforms, paths must be less than 248 characters and file names must be less than 260 characters.</exception>/// <exception cref="T:System.ArgumentNullException"><paramref name="path" /> is null.</exception>/// <exception cref="T:System.ArgumentException"><paramref name="path" /> is a zero-length string, contains only white space, or contains one or more invalid characters as defined by <see cref="F:System.IO.Path.InvalidPathChars" />.</exception>[NotNull]publicstaticIEnumerable<string>GetAllFiles([NotNull]string directory){foreach(string file inDirectory.GetFiles(directory)){yieldreturn file;// includes the path}foreach(string subDir inDirectory.GetDirectories(directory)){foreach(string subFile inGetAllFiles(subDir)){yieldreturn subFile;}}}
Вот мой взгляд на это, основанный на Эрнальдо, если вам нужно найти файлы с именами определенного шаблона, например, XML-файлы, которые где-то в их имени содержат определенную строку:
// call this like so: GetXMLFiles("Platypus", "C:\\");publicstaticList<string>GetXMLFiles(string fileType,string dir){string dirName = dir;var fileNames =newList<String>();try{foreach(string f inDirectory.GetFiles(dirName)){if((f.Contains(fileType))&&(f.Contains(".XML"))){
fileNames.Add(f);}}foreach(string d inDirectory.GetDirectories(dirName)){GetXMLFiles(fileType, d);}}catch(Exception ex){MessageBox.Show(ex.Message);}return fileNames;}
Список файлов и папок для моделирования, пользовательская реализация.
Это создает полный список всех файлов и папок, начиная с вашего начального каталога.
Вывод функции (содержимое папки 5 исключено из-за ограничения lvl, а содержимое папки 3 исключено, поскольку оно находится в массиве exclusiveFolders):
publicstaticList<string>AllFilesInFolder(string folder){var result =newList<string>();foreach(string f inDirectory.GetFiles(folder)){
result.Add(f);}foreach(string d inDirectory.GetDirectories(folder)){
result.AddRange(AllFilesInFolder(d));}return result;}
staticvoidMain(string[] args){string[] array1 =Directory.GetFiles(@"D:\");string[] array2 =System.IO.Directory.GetDirectories(@"D:\");Console.WriteLine("--- Files: ---");foreach(string name in array1){Console.WriteLine(name);}foreach(string name in array2){Console.WriteLine(name);}Console.ReadLine();}
Ответы:
Эта статья охватывает все, что вам нужно. За исключением случаев поиска файлов и сравнения имен, просто распечатайте имена.
Это может быть изменено так:
Добавил барлоп
GONeale упоминает, что выше не перечисляет файлы в текущем каталоге и предлагает поместить часть списка файлов вне той части, которая получает каталоги. Следующее сделало бы это. Он также включает строку Writeline, которую вы можете раскомментировать, которая помогает отследить, где вы находитесь в рекурсии, что может помочь показать вызовы, чтобы показать, как работает рекурсия.
источник
Обратите внимание, что в .NET 4.0 есть (предположительно) основанные на итераторах (а не на основе массивов) файловые функции, встроенные в:
На данный момент я бы использовал что-то вроде ниже; встроенный рекурсивный метод ломается слишком легко, если у вас нет доступа к одному подкаталогу ...;
Queue<string>
использование позволяет избежать слишком много вызовов стеки рекурсии, и блок итератора избегает нас , имеющими огромный массива.источник
*.*
включает ли также файлы без расширения: Да, это так, протестировано минуту назад.using System.IO;
Console
вам нужно будет добавитьusing System;
- но, поскольку IDE может добавить все необходимыеusing
директивы для вас (ctrl +.), И поскольку мы не используем здесь ничего экзотического, обычно их не включают. Черт возьми, тебе тоже понадобитсяclass
определение и т. Д. Просто скажиисточник
В .NET 4.5, по крайней мере, есть эта версия, которая намного короче и имеет дополнительный бонус оценки любых критериев файла для включения в список:
Используйте как это:
источник
источник
В Framework 2.0 вы можете использовать (в нем перечислены файлы корневой папки, лучше всего самый популярный ответ):
источник
Некоторые отличные ответы, но эти ответы не решили мою проблему.
Как только возникает проблема с разрешением папки: «Отказано в доступе», код завершается ошибкой. Вот что я использовал для решения проблемы «Отказано в доступе»:
Надеюсь, что это помогает другим.
источник
Простое и чистое решение
источник
Я предпочитаю использовать DirectoryInfo, потому что я могу получить FileInfo, а не только строки.
Я делаю это на случай, если в будущем мне понадобится будущая фильтрация .. на основе свойств FileInfo.
Я также могу прибегнуть к последовательности, если это будет необходимо. (и до сих пор пригоден для использования в фильтрах / пунктах).
Обратите внимание, что « . » Является допустимым шаблоном поиска, если вы хотите подать файл по расширению.
источник
источник
files
естьref
? Нет необходимости.files
и вы больше не сможете простоnew List<FileInfo>()
указывать в качестве параметра, который был бы бесполезен. Может позволить некоторую подоптимизацию и избежать создания нового объекта, если это не требуется.ref
ничего не проясняет.ref
Цель «s, чтобы изменить весьfiles
указатель даже для вызывающей метод: это опасная операция , и здесь нет необходимости в том , что вы можете просто заполнить список, вам не нужно повторно точки в другой список на кучаref
следует использовать только в очень особых случаях; В большинстве случаев вам просто нужно реализовать что-то более функционально-парадигмальное.Чтобы избежать
UnauthorizedAccessException
, я использую:источник
Если вам нужны только имена файлов, и, поскольку мне не очень нравятся большинство решений здесь (по функциональности или по удобочитаемости), как насчет этого ленивого?
источник
Кратчайшая запись
источник
Вот мой взгляд на это, основанный на Эрнальдо, если вам нужно найти файлы с именами определенного шаблона, например, XML-файлы, которые где-то в их имени содержат определенную строку:
источник
Список файлов и папок для моделирования, пользовательская реализация.
Это создает полный список всех файлов и папок, начиная с вашего начального каталога.
Метод:
Использование:
источник
Краткое и простое решение
источник
Этот помог мне собрать все файлы в каталог и подкаталоги, может быть, кому-то пригодится. [Вдохновленный сверху ответы]
источник
источник
Некоторая улучшенная версия с max lvl для перехода в каталог и опцией для исключения папок:
входной каталог:
Вывод функции (содержимое папки 5 исключено из-за ограничения lvl, а содержимое папки 3 исключено, поскольку оно находится в массиве exclusiveFolders):
источник
Вот версия кода Б. Клэя Шеннона, не статичная для файлов Excel:
источник
Очень простое решение, возвращает список файлов.
источник
источник