在所有子目录中查找具有特定扩展名的文件数
有没有办法找到特定类型的文件数,而无需在Directory.GetFiles()或类似方法中循环遍历所有结果? 我正在寻找这样的东西:
int ComponentCount = MagicFindFileCount(@"c:\windows\system32", "*.dll");
我知道我可以创建一个递归函数来调用Directory.GetFiles,但是如果我可以在没有所有迭代的情况下执行此操作,那将会更加清晰。
编辑:如果没有递归和迭代自己不可能做到这一点,那么最好的方法是什么?
您应该使用Directory.GetFiles()的Directory.GetFiles(path,searchPattern,SearchOption)重载。
Path指定路径,searchPattern指定通配符(例如,*,*。format),SearchOption提供包含子目录的选项。
此搜索的返回数组的Length属性将为您的特定搜索模式和选项提供正确的文件计数:
string[] files = directory.GetFiles(@"c:\windows\system32", "*.dll", SearchOption.AllDirectories); return files.Length;
编辑:或者您可以使用Directory.EnumerateFiles方法
return Directory.EnumerateFiles(@"c:\windows\system32", "*.dll", SearchOption.AllDirectories).Count();
最简单的方法是使用linq:
var fileCount = (from file in Directory.EnumerateFiles(@"H:\iPod_Control\Music", "*.mp3", SearchOption.AllDirectories) select file).Count();
您可以使用GetFiles的这个重载:
Directory.GetFiles方法(String,String,SearchOption )
和SearchOption的这个成员:
AllDirectories – 包括搜索操作中的当前目录和所有子目录。 此选项包括重新分析点,如安装的驱动器和搜索中的符号链接。
GetFiles返回一个字符串数组,因此您只需获取Length,即找到的文件数。
我一直在寻找更优化的版本。 由于我还没有找到它,我决定编码并在此处分享:
public static int GetFileCount(string path, string searchPattern, SearchOption searchOption) { var fileCount = 0; var fileIter = Directory.EnumerateFiles(path, searchPattern, searchOption); foreach (var file in fileIter) fileCount++; return fileCount; }
使用GetFiles / GetDirectories的所有解决方案都很慢,因为需要创建所有这些对象。 使用枚举,它不会创建任何临时对象(FileInfo / DirectoryInfo)。
有关更多信息,请参阅备注http://msdn.microsoft.com/en-us/library/dd383571.aspx
使用递归,您的MagicFindFileCount将如下所示:
private int MagicFindFileCount( string strDirectory, string strFilter ) { int nFiles = Directory.GetFiles( strDirectory, strFilter ).Length; foreach( String dir in Directory.GetDirectories( strDirectory ) ) { nFiles += GetNumberOfFiles(dir, strFilter); } return nFiles; }
虽然乔恩的解决方案可能更好。
我有一个应用程序,它生成父目录中的目录和文件的计数。 一些目录包含数千个子目录,每个目录中包含数千个文件。 要在保持响应式ui的同时执行此操作,请执行以下操作(将路径发送到ADirectoryPathWasSelected方法):
public class DirectoryFileCounter { int mDirectoriesToRead = 0; // Pass this method the parent directory path public void ADirectoryPathWasSelected(string path) { // create a task to do this in the background for responsive ui // state is the path Task.Factory.StartNew((state) => { try { // Get the first layer of sub directories this.AddCountFilesAndFolders(state.ToString()) } catch // Add Handlers for exceptions {} }, path)); } // This method is called recursively private void AddCountFilesAndFolders(string path) { try { // Only doing the top directory to prevent an exception from stopping the entire recursion var directories = Directory.EnumerateDirectories(path, "*.*", SearchOption.TopDirectoryOnly); // calling class is tracking the count of directories this.mDirectoriesToRead += directories.Count(); // get the child directories // this uses an extension method to the IEnumerable interface, // which will run a function on an object. In this case 'd' is the // collection of directories directories.ActionOnEnumerable(d => AddCountFilesAndFolders(d)); } catch // Add Handlers for exceptions { } try { // count the files in the directory this.mFilesToRead += Directory.EnumerateFiles(path).Count(); } catch// Add Handlers for exceptions { } } } // Extension class public static class Extensions { // this runs the supplied method on each object in the supplied enumerable public static void ActionOnEnumerable (this IEnumerable nodes,Action doit) { foreach (var node in nodes) { doit(node); } } }
有人必须做迭代部分。
AFAIK,.NET中已经没有这样的方法,所以我想有人必须是你。