最快/最安全的文件查找/解析?

c: ,我有成千上万的*.foobar文件。 他们在各种各样的地方(即子市场)。 这些文件大小约为1-64 kb,并且是纯文本。

我有一个class Foobar(string fileContents)强类型这些.foobar文件。

我的挑战是获取c:上所有*.foobar文件的列表,表示为Foobar对象的数组。 最快的方法是什么?

我很想知道是否有一种比我的第一种方法更好的方式(毫无疑问),如果我的这种方法有任何潜在的问题(例如I / O并发问题抛出exception?):

 var files = Directory.EnumerateFiles (rootPath, "*.foobar", SearchOption.AllDirectories); Foobar[] foobars = ( from filePath in files.AsParallel() let contents = File.ReadAllText(filePath) select new Foobar(contents) ) .ToArray(); 

因为权限错误(或其他错误)显然会使枚举停止在其轨道中,所以您可能希望实现自己的枚举器,如下所示:

 class SafeFileEnumerator : IEnumerable { private string root; private string pattern; private IList errors; public SafeFileEnumerator(string root, string pattern) { this.root = root; this.pattern = pattern; this.errors = new List(); } public SafeFileEnumerator(string root, string pattern, IList errors) { this.root = root; this.pattern = pattern; this.errors = errors; } public Exception[] Errors() { return errors.ToArray(); } class Enumerator : IEnumerator { IEnumerator fileEnumerator; IEnumerator directoryEnumerator; string root; string pattern; IList errors; public Enumerator(string root, string pattern, IList errors) { this.root = root; this.pattern = pattern; this.errors = errors; fileEnumerator = System.IO.Directory.EnumerateFiles(root, pattern).GetEnumerator(); directoryEnumerator = System.IO.Directory.EnumerateDirectories(root).GetEnumerator(); } public string Current { get { if (fileEnumerator == null) throw new ObjectDisposedException("FileEnumerator"); return fileEnumerator.Current; } } public void Dispose() { if (fileEnumerator != null) fileEnumerator.Dispose(); fileEnumerator = null; if (directoryEnumerator != null) directoryEnumerator.Dispose(); directoryEnumerator = null; } object System.Collections.IEnumerator.Current { get { return Current; } } public bool MoveNext() { if ((fileEnumerator != null) && (fileEnumerator.MoveNext())) return true; while ((directoryEnumerator != null) && (directoryEnumerator.MoveNext())) { if (fileEnumerator != null) fileEnumerator.Dispose(); try { fileEnumerator = new SafeFileEnumerator(directoryEnumerator.Current, pattern, errors).GetEnumerator(); } catch (Exception ex) { errors.Add(ex); continue; } if (fileEnumerator.MoveNext()) return true; } if (fileEnumerator != null) fileEnumerator.Dispose(); fileEnumerator = null; if (directoryEnumerator != null) directoryEnumerator.Dispose(); directoryEnumerator = null; return false; } public void Reset() { Dispose(); fileEnumerator = System.IO.Directory.EnumerateFiles(root, pattern).GetEnumerator(); directoryEnumerator = System.IO.Directory.EnumerateDirectories(root).GetEnumerator(); } } public IEnumerator GetEnumerator() { return new Enumerator(root, pattern, errors); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); } } 

很棒的工作,这里是代码的扩展,返回FileSystemInfo而不是字符串路径。 行中的一些小改动,比如添加SearchOption(就像本机.net一样),以及初始目录上的错误捕获,以防根文件夹被拒绝访问。 再次感谢原帖!

 public class SafeFileEnumerator : IEnumerable { ///  /// Starting directory to search from ///  private DirectoryInfo root; ///  /// Filter pattern ///  private string pattern; ///  /// Indicator if search is recursive or not ///  private SearchOption searchOption; ///  /// Any errors captured ///  private IList errors; ///  /// Create an Enumerator that will scan the file system, skipping directories where access is denied ///  /// Starting Directory /// Filter pattern /// Recursive or not public SafeFileEnumerator(string root, string pattern, SearchOption option) : this(new DirectoryInfo(root), pattern, option) {} ///  /// Create an Enumerator that will scan the file system, skipping directories where access is denied ///  /// Starting Directory /// Filter pattern /// Recursive or not public SafeFileEnumerator(DirectoryInfo root, string pattern, SearchOption option) : this(root, pattern, option, new List()) {} // Internal constructor for recursive itterator private SafeFileEnumerator(DirectoryInfo root, string pattern, SearchOption option, IList errors) { if (root == null || !root.Exists) { throw new ArgumentException("Root directory is not set or does not exist.", "root"); } this.root = root; this.searchOption = option; this.pattern = String.IsNullOrEmpty(pattern) ? "*" : pattern; this.errors = errors; } ///  /// Errors captured while parsing the file system. ///  public Exception[] Errors { get { return errors.ToArray(); } } ///  /// Helper class to enumerate the file system. ///  private class Enumerator : IEnumerator { // Core enumerator that we will be walking though private IEnumerator fileEnumerator; // Directory enumerator to capture access errors private IEnumerator directoryEnumerator; private DirectoryInfo root; private string pattern; private SearchOption searchOption; private IList errors; public Enumerator(DirectoryInfo root, string pattern, SearchOption option, IList errors) { this.root = root; this.pattern = pattern; this.errors = errors; this.searchOption = option; Reset(); } ///  /// Current item the primary itterator is pointing to ///  public FileSystemInfo Current { get { //if (fileEnumerator == null) throw new ObjectDisposedException("FileEnumerator"); return fileEnumerator.Current as FileSystemInfo; } } object System.Collections.IEnumerator.Current { get { return Current; } } public void Dispose() { Dispose(true, true); } private void Dispose(bool file, bool dir) { if (file) { if (fileEnumerator != null) fileEnumerator.Dispose(); fileEnumerator = null; } if (dir) { if (directoryEnumerator != null) directoryEnumerator.Dispose(); directoryEnumerator = null; } } public bool MoveNext() { // Enumerate the files in the current folder if ((fileEnumerator != null) && (fileEnumerator.MoveNext())) return true; // Don't go recursive... if (searchOption == SearchOption.TopDirectoryOnly) { return false; } while ((directoryEnumerator != null) && (directoryEnumerator.MoveNext())) { Dispose(true, false); try { fileEnumerator = new SafeFileEnumerator( directoryEnumerator.Current, pattern, SearchOption.AllDirectories, errors ).GetEnumerator(); } catch (Exception ex) { errors.Add(ex); continue; } // Open up the current folder file enumerator if (fileEnumerator.MoveNext()) return true; } Dispose(true, true); return false; } public void Reset() { Dispose(true,true); // Safely get the enumerators, including in the case where the root is not accessable if (root != null) { try { fileEnumerator = root.GetFileSystemInfos(pattern, SearchOption.TopDirectoryOnly).AsEnumerable().GetEnumerator(); } catch (Exception ex) { errors.Add(ex); fileEnumerator = null; } try { directoryEnumerator = root.GetDirectories(pattern, SearchOption.TopDirectoryOnly).AsEnumerable().GetEnumerator(); } catch (Exception ex) { errors.Add(ex); directoryEnumerator = null; } } } } public IEnumerator GetEnumerator() { return new Enumerator(root, pattern, searchOption, errors); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); } }