首先,请原谅我糟糕的英语;o)
我有一个问题将我带到此页面:枚举目录及其子目录的文件而不阻塞 UnauthorizedAccessException,并且像 .Net 4 DirectoryInfo.Enumerate... 的新方法一样,在结束之前获得第一个结果整个查询。
借助网上到处找的各种例子,我终于写出了这个方法:
public static IEnumerable<FileInfo> EnumerateFiles_Recursive(this DirectoryInfo directory, string searchPattern, SearchOption searchOption, Func<DirectoryInfo, Exception, bool> handleExceptionAccess)
{
Queue<DirectoryInfo> subDirectories = new Queue<DirectoryInfo>();
IEnumerable<FileSystemInfo> entries = null;
// Try to get an enumerator on fileSystemInfos of directory
try
{
entries = directory.EnumerateFileSystemInfos(searchPattern, SearchOption.TopDirectoryOnly);
}
catch (Exception e)
{
// If there's a callback delegate and this delegate return true, we don't throw the exception
if (handleExceptionAccess == null || !handleExceptionAccess(directory, e))
throw;
// If the exception wasn't throw, we make entries reference an empty collection
entries = EmptyFileSystemInfos;
}
// Yield return file entries of the directory and enqueue the subdirectories
foreach (FileSystemInfo entrie in entries)
{
if (entrie is FileInfo)
yield return (FileInfo)entrie;
else if (entrie is DirectoryInfo)
subDirectories.Enqueue((DirectoryInfo)entrie);
}
// If recursive search, we make recursive call on the method to yield return entries of the subdirectories.
if (searchOption == SearchOption.AllDirectories)
{
DirectoryInfo subDir = null;
while (subDirectories.Count > 0)
{
subDir = subDirectories.Dequeue();
foreach (FileInfo file in subDir.EnumerateFiles_Recursive(searchPattern, searchOption, handleExceptionAccess))
{
yield return file;
}
}
}
else
subDirectories.Clear();
}
我使用队列和递归方法来保持传统顺序(目录内容,然后是第一个子目录的内容和他自己的子目录,然后是第二个子目录的内容......)。参数“handleExceptionAccess”只是一个目录抛出异常时的函数调用;该函数必须返回 true 以指示该异常必须被忽略。
用这个方法,你可以写:
DirectoryInfo dir = new DirectoryInfo("c:\\temp");
long size = dir.EnumerateFiles_Recursive("*", SearchOption.AllDirectories, (d, ex) => true).Sum(f => f.Length);
我们在这里:尝试枚举目录时的所有异常都将被忽略!
希望有帮助
莱昂内尔
PS : 由于一个我无法解释的原因,我的方法比框架 4 更快...
PPS:您可以通过这些方法的源代码获取我的测试解决方案:这里是TestDirEnumerate。我写了 EnumerateFiles_Recursive、EnumerateFiles_NonRecursive(使用队列来避免递归)和 EnumerateFiles_NonRecursive_TraditionalOrder(使用队列堆栈来避免递归并保持传统顺序)。保留这三种方法没有任何意义,我写它们只是为了测试最好的一种。我想只保留最后一个。
我还为 EnumerateFileSystemInfos 和 EnumerateDirectories 编写了等效项。