c# - 如何在 C# 中将文件枚举到只有 3 个文件目录?
问题描述
目前我只能 Enumeratefiles 方法所有文件或源目录。我希望它深入 3 个子目录,然后只检查那里。
例如,第二个片段将只检查 K:\SourceFolder
第一个示例将检查 K:\SourceFolder\JobName\Batches\Folder1\Folder11\Images 它将检查所有文件夹,因此会降低应用程序的性能和效率。
我也只需要它检查 K:\SourceFolder\JobName\Batches
这段代码走得太远了:
List<string> validFiles = new List<string>();
List<string> files = Directory.EnumerateFiles(folderPath, "*.*", SearchOption.AllDirectories).ToList();
foreach (var file in files)
这段代码还不够:
List<string> files = Directory.Enumeratefiles(directory)
解决方案
我们可以使用几种不同的方法来解决此任务,因此我将列出一些示例以帮助入门。
使用循环迭代所有文件夹并仅返回目标深度的文件夹:
List<string> ListFilesAtSpecificDepth(string rootPath, int targetDepth)
{
// Set the root folder before we start iterating through subfolders.
var foldersAtCurrentDepth = Directory.EnumerateDirectories(rootPath).ToList(); // calling ToList will make the enumeration happen now.
for (int currentDepth = 0; currentDepth < targetDepth; currentDepth++)
{
// Using select many is a clean way to select the subfolders for multiple root folders into a flat list.
foldersAtCurrentDepth = foldersAtCurrentDepth.SelectMany(x => Directory.EnumerateDirectories(x)).ToList();
}
// After the loop we have a list of folders for the targetDepth only.
// Select many again to get all the files for all the folders.
return foldersAtCurrentDepth.SelectMany(x => Directory.EnumerateFiles(x, "*.*", SearchOption.TopDirectoryOnly)).ToList();
}
另一种选择是使用递归来调用相同的方法,直到我们达到所需的深度。这可用于仅返回目标深度的结果或沿途的所有结果,因为上面的示例只返回目标深度,我决定使用自定义对象来跟踪深度的所有结果:
class FileSearchResult
{
public string FilePath {get;set;}
public int FolderDepthFromRoot {get;set;}
}
List<FileSearchResult> ListFilesUntilSpecificDepth(string rootPath, int maxDepth, int currentDepth = 0)
{
// Add all the files at the current level along with extra details like the depth.
var iterationResult = Directory.EnumerateFiles(rootPath, "*.*", SearchOption.TopDirectoryOnly)
.Select(x => new FileSearchResult
{
FilePath = x,
FolderDepthFromRoot = currentDepth
}).ToList();
if (currentDepth < maxDepth) // we need to go deeper.
{
var foldersUnderMe = Directory.EnumerateDirectories(rootPath);
// Add all the results for subfolders recursively by calling the same method again.
foreach (var subFolder in foldersUnderMe)
{
iterationResult.AddRange(ListFilesUntilSpecificDepth(subFolder, maxDepth, currentDepth + 1))
}
}
return iterationResult;
}
介绍了递归和循环的例子,最后我想谈的是使用文件系统本身的结构来帮助完成这项任务。因此,我们可以使用原始方法递归地获取所有文件,然后使用所有结果的列表来确定深度,而不是管理我们自己的循环或递归。例如,我们知道“/”是文件系统用来分隔文件夹的字符,并且在文件夹或文件名中使用它是非法字符,因此使用此标记来有效地计算文件夹应该是非常安全的。在此示例中,我将使用另一个自定义类来跟踪结果,因此它应该有效地返回与递归方法相同的结果,但具有无限深度。
class FileSearchResult
{
public string FilePath { get; set; }
public int FolderDepthFromRoot { get; set; }
}
List<FileSearchResult> ListFiles(string rootPath)
{
var allFiles = Directory.EnumerateFiles(rootPath, "*.*", SearchOption.AllDirectories).ToList();
int numberOfFoldersInRootPath = rootPath.Count(c => c == '\\'); // count how many backslashes in root path as a base.
return allFiles.Select(filePath => new FileSearchResult
{
FilePath = filePath,
FolderDepthFromRoot = filePath.Count(c => c == '\\') - numberOfFoldersInRootPath
}).ToList();
}
推荐阅读
- bash - 周日使用 shell 脚本创建的列表文件
- c++ - 尝试从 C++ 中的 ini 文件中读取
- java - 从文档中计算一天中不同的小时数
- apache - 子目录中特定文件类型的 Apache 代理/重写设置
- mysql - 根据另一列中的最小值更新重复记录
- mysql - MYSQL:带有详细信息和未读消息计数的朋友列表
- php - Codeigniter 在用户 Apache 下写入/创建文件夹
- matlab - 如果变量取决于优化变量,如何编写优化程序?
- android - 错误:未知平台:“OSX”。请使用 DeveloperTools 提交 ContactUs
- sql-server - 有没有办法将 select 子句与 where 子句应用条件从另一个 select 子句驱动?