Ich versuche, eine Liste aller Dateien anzuzeigen, die im ausgewählten Verzeichnis gefunden wurden (und optional alle Unterverzeichnisse). Das Problem, das ich habe, ist, dass wenn die GetFiles () -Methode auf einen Ordner stößt, auf den sie nicht zugreifen kann, eine Ausnahme ausgelöst wird und der Prozess gestoppt wird.
Wie ignoriere ich diese Ausnahme (und ignoriere den geschützten Ordner / die geschützte Datei) und füge der Liste weiterhin zugängliche Dateien hinzu?
try
{
if (cbSubFolders.Checked == false)
{
string[] files = Directory.GetFiles(folderBrowserDialog1.SelectedPath);
foreach (string fileName in files)
ProcessFile(fileName);
}
else
{
string[] files = Directory.GetFiles(folderBrowserDialog1.SelectedPath, "*.*", SearchOption.AllDirectories);
foreach (string fileName in files)
ProcessFile(fileName);
}
lblNumberOfFilesDisplay.Enabled = true;
}
catch (UnauthorizedAccessException) { }
finally {}
GetFiles
oderGetDirectories
beide können Ausnahmen auslösen, sodass Sie nach der Ausnahme nichts mehr sehen.Diese einfache Funktion funktioniert gut und erfüllt die Anforderungen der Fragen.
private List<string> GetFiles(string path, string pattern) { var files = new List<string>(); var directories = new string[] { }; try { files.AddRange(Directory.GetFiles(path, pattern, SearchOption.TopDirectoryOnly)); directories = Directory.GetDirectories(path); } catch (UnauthorizedAccessException) { } foreach (var directory in directories) try { files.AddRange(GetFiles(directory, pattern)); } catch (UnauthorizedAccessException) { } return files; }
quelle
GetFiles
Befehl auslösen, können Sie danach nichts mehr sehen.Eine einfache Möglichkeit hierfür ist die Verwendung einer Liste für Dateien und einer Warteschlange für Verzeichnisse. Es schont das Gedächtnis. Wenn Sie ein rekursives Programm verwenden, um dieselbe Aufgabe auszuführen, kann dies zu einer OutOfMemory-Ausnahme führen. Die in der Liste hinzugefügten Ausgabedateien sind nach dem Verzeichnisbaum von oben nach unten (Breite zuerst) organisiert.
public static List<string> GetAllFilesFromFolder(string root, bool searchSubfolders) { Queue<string> folders = new Queue<string>(); List<string> files = new List<string>(); folders.Enqueue(root); while (folders.Count != 0) { string currentFolder = folders.Dequeue(); try { string[] filesInCurrent = System.IO.Directory.GetFiles(currentFolder, "*.*", System.IO.SearchOption.TopDirectoryOnly); files.AddRange(filesInCurrent); } catch { // Do Nothing } try { if (searchSubfolders) { string[] foldersInCurrent = System.IO.Directory.GetDirectories(currentFolder, "*.*", System.IO.SearchOption.TopDirectoryOnly); foreach (string _current in foldersInCurrent) { folders.Enqueue(_current); } } } catch { // Do Nothing } } return files; }
Schritte:
quelle
Seit .NET Standard 2.1 können Sie jetzt einfach Folgendes tun:
var filePaths = Directory.EnumerateFiles(@"C:\my\files", "*.xml", new EnumerationOptions { IgnoreInaccessible = true, RecurseSubdirectories = true });
Laut den MSDN-Dokumenten zu IgnoreInaccessible :
Der Standardwert ist tatsächlich wahr, aber ich habe ihn hier beibehalten, um die Eigenschaft anzuzeigen.
Die gleiche Überlastung ist auch für verfügbar
DirectoryInfo
.quelle
Unter https://stackoverflow.com/a/10728792/89584 finden Sie eine Lösung für das Problem UnauthorisedAccessException.
Bei allen oben genannten Lösungen fehlen Dateien und / oder Verzeichnisse, wenn Aufrufe von GetFiles () oder GetDirectories () in Ordnern mit unterschiedlichen Berechtigungen erfolgen.
quelle
Dies sollte die Frage beantworten. Ich habe das Problem des Durchsuchens von Unterverzeichnissen ignoriert. Ich gehe davon aus, dass Sie das herausgefunden haben.
Natürlich benötigen Sie hierfür keine separate Methode, aber möglicherweise ist dies ein nützlicher Ort, um auch zu überprüfen, ob der Pfad gültig ist, und um die anderen Ausnahmen zu behandeln, die beim Aufrufen von GetFiles () auftreten können.
Hoffe das hilft.
private string[] GetFiles(string path) { string[] files = null; try { files = Directory.GetFiles(path); } catch (UnauthorizedAccessException) { // might be nice to log this, or something ... } return files; } private void Processor(string path, bool recursive) { // leaving the recursive directory navigation out. string[] files = this.GetFiles(path); if (null != files) { foreach (string file in files) { this.Process(file); } } else { // again, might want to do something when you can't access the path? } }
quelle
Hier ist eine voll funktionsfähige, .NET 2.0-kompatible Implementierung.
Sie können sogar die Anzahl
List
der Dateien ändern , um Verzeichnisse in derFileSystemInfo
Version zu überspringen !(Vorsicht vor
null
Werten!)public static IEnumerable<KeyValuePair<string, string[]>> GetFileSystemInfosRecursive(string dir, bool depth_first) { foreach (var item in GetFileSystemObjectsRecursive(new DirectoryInfo(dir), depth_first)) { string[] result; var children = item.Value; if (children != null) { result = new string[children.Count]; for (int i = 0; i < result.Length; i++) { result[i] = children[i].Name; } } else { result = null; } string fullname; try { fullname = item.Key.FullName; } catch (IOException) { fullname = null; } catch (UnauthorizedAccessException) { fullname = null; } yield return new KeyValuePair<string, string[]>(fullname, result); } } public static IEnumerable<KeyValuePair<DirectoryInfo, List<FileSystemInfo>>> GetFileSystemInfosRecursive(DirectoryInfo dir, bool depth_first) { var stack = depth_first ? new Stack<DirectoryInfo>() : null; var queue = depth_first ? null : new Queue<DirectoryInfo>(); if (depth_first) { stack.Push(dir); } else { queue.Enqueue(dir); } for (var list = new List<FileSystemInfo>(); (depth_first ? stack.Count : queue.Count) > 0; list.Clear()) { dir = depth_first ? stack.Pop() : queue.Dequeue(); FileSystemInfo[] children; try { children = dir.GetFileSystemInfos(); } catch (UnauthorizedAccessException) { children = null; } catch (IOException) { children = null; } if (children != null) { list.AddRange(children); } yield return new KeyValuePair<DirectoryInfo, List<FileSystemInfo>>(dir, children != null ? list : null); if (depth_first) { list.Reverse(); } foreach (var child in list) { var asdir = child as DirectoryInfo; if (asdir != null) { if (depth_first) { stack.Push(asdir); } else { queue.Enqueue(asdir); } } } } }
quelle
Ich bevorzuge die Verwendung von c # Framework-Funktionen, aber die Funktion, die ich benötige, wird in .net Framework 5.0 enthalten sein, also muss ich sie schreiben.
// search file in every subdirectory ignoring access errors static List<string> list_files(string path) { List<string> files = new List<string>(); // add the files in the current directory try { string[] entries = Directory.GetFiles(path); foreach (string entry in entries) files.Add(System.IO.Path.Combine(path,entry)); } catch { // an exception in directory.getfiles is not recoverable: the directory is not accessible } // follow the subdirectories try { string[] entries = Directory.GetDirectories(path); foreach (string entry in entries) { string current_path = System.IO.Path.Combine(path, entry); List<string> files_in_subdir = list_files(current_path); foreach (string current_file in files_in_subdir) files.Add(current_file); } } catch { // an exception in directory.getdirectories is not recoverable: the directory is not accessible } return files; }
quelle