提问人:Rod 提问时间:3/3/2011 最后编辑:bluishRod 更新时间:11/24/2020 访问量:104930
迭代文件夹和子文件夹的最佳方式
Best way to iterate folders and subfolders
答:
47赞
Lloyd
3/3/2011
#1
使用 Directory.GetFiles()。该页面的底部包含一个完全递归的示例。
注意:在使用 .NET 4 及更高版本时,请使用下面的 Chris Dunaway 的答案来获得更现代的方法。
// For Directory.GetFiles and Directory.GetDirectories
// For File.Exists, Directory.Exists
using System;
using System.IO;
using System.Collections;
public class RecursiveFileProcessor
{
public static void Main(string[] args)
{
foreach(string path in args)
{
if(File.Exists(path))
{
// This path is a file
ProcessFile(path);
}
else if(Directory.Exists(path))
{
// This path is a directory
ProcessDirectory(path);
}
else
{
Console.WriteLine("{0} is not a valid file or directory.", path);
}
}
}
// Process all files in the directory passed in, recurse on any directories
// that are found, and process the files they contain.
public static void ProcessDirectory(string targetDirectory)
{
// Process the list of files found in the directory.
string [] fileEntries = Directory.GetFiles(targetDirectory);
foreach(string fileName in fileEntries)
ProcessFile(fileName);
// Recurse into subdirectories of this directory.
string [] subdirectoryEntries = Directory.GetDirectories(targetDirectory);
foreach(string subdirectory in subdirectoryEntries)
ProcessDirectory(subdirectory);
}
// Insert logic for processing found files here.
public static void ProcessFile(string path)
{
Console.WriteLine("Processed file '{0}'.", path);
}
}
评论
1赞
quentin-starin
5/14/2011
需要注意的是:Directory.GetFiles() 对于包含大量文件(10 到 100 个数千个)的目录可能会非常慢。在这些情况下,到目前为止,我发现的最快方法实际上是启动一个进程来运行命令并重定向输出并解析它(或通过管道进入文件并读取它)。当然,除非我期望单个目录中有 50,000+ 个文件,否则我不会考虑这一点。dir
0赞
Lloyd
1/15/2013
实际上,调用等而不是使用可能会更快,尽管我敢肯定 .NET 无论如何都会解决这个问题。FindFirstFile
dir
1赞
Rune Grimstad
3/3/2011
#2
若要循环访问文件和文件夹,通常使用 DirectoryInfo 和 FileInfo 类型。FileInfo 类型具有一个 Length 属性,该属性返回文件大小(以字节为单位)。
我认为您必须编写自己的代码来遍历文件并计算总文件大小,但这应该是一个非常简单的递归函数。
8赞
safi
3/3/2011
#3
遍历所有目录子文件夹和文件,无论子文件夹和文件有多少。
string [] filenames;
fname = Directory.GetFiles(jak, "*.*", SearchOption.AllDirectories).Select(x => Path.GetFileName(x)).ToArray();
然后,您可以从数组中通过循环或根据需要获得所需的内容。
评论
1赞
Anthony Wieser
10/2/2013
如果您的文件夹结构中存在循环,这将无限循环:请参阅 msdn.microsoft.com/en-us/library/ms143448.aspx
1赞
HuBeZa
3/3/2011
#4
请注意,您将需要执行验证检查。
string[] fileNames = Directory.GetFiles("c:\\", "*.*", SearchOption.AllDirectories);
int fileCount = fileNames.Count();
long fileSize = fileNames.Select(file => new FileInfo(file).Length).Sum(); // in bytes
评论
0赞
Rod
3/3/2011
什么类型的验证检查
0赞
HuBeZa
3/3/2011
@rod:检查是否(否则,)。我想不出别的了,但也许我错过了什么。Directory.Exists
DirectoryNotFoundException
59赞
Chris Dunaway
3/4/2011
#5
如果您使用的是 .NET 4,您可能希望使用 and 方法。如果您按照其他帖子的建议使用该方法,则在检索到所有条目之前,方法调用不会返回。如果您使用递归,这可能需要很长时间。System.IO.DirectoryInfo.EnumerateDirectories
System.IO.DirectoryInfo.EnumerateFiles
Directory.GetFiles
从文档中:
和方法的区别如下:
EnumerateFiles
GetFiles
- 使用 时,可以在整个集合之前开始枚举对象的集合 返回。
EnumerateFiles
FileInfo
- 使用 时,必须等待返回整个对象数组,然后才能访问该数组。
GetFiles
FileInfo
因此,当您处理许多文件和目录时,效率会更高。
EnumerateFiles
评论
2赞
krowe2
8/15/2018
不得不跳过十几个使用 GetDirectory() 的示例来找到这个。对于 >50k 目录,速度太慢了。谢谢你拯救了我一天的罕见例子。
5赞
S4NT14G0
10/23/2019
#6
下面是一个使用上面 Peter 的建议和递归的示例。
using System;
using System.IO;
namespace FileSystemUtils
{
class Program
{
static void Main(string[] args)
{
string folderPath = "C:\\docs";
DirectoryInfo startDir = new DirectoryInfo(folderPath);
RecurseFileStructure recurseFileStructure = new RecurseFileStructure();
recurseFileStructure.TraverseDirectory(startDir);
}
public class RecurseFileStructure
{
public void TraverseDirectory(DirectoryInfo directoryInfo)
{
var subdirectories = directoryInfo.EnumerateDirectories();
foreach (var subdirectory in subdirectories)
{
TraverseDirectory(subdirectory);
}
var files = directoryInfo.EnumerateFiles();
foreach (var file in files)
{
HandleFile(file);
}
}
void HandleFile(FileInfo file)
{
Console.WriteLine("{0}", file.Name);
}
}
}
}
评论