c# - 在 .NET Core 中使用 System.IO.Enumeration 自定义目录枚举
问题描述
这篇文章的作者提到有一个更新的 API 用于更快的文件和目录枚举方法。但是,尽管这篇文章似乎提到了示例,但它们并不存在,而且我在 Google 的其他地方找不到任何使用提到的新方法的示例?
有没有人有一些示例代码可以枚举给定文件夹和所有子文件夹/文件以返回诸如大小和上次访问等信息?
解决方案
我明白为什么您发现很难弄清楚这一点 - 周围没有太多信息,所以我最终挖掘了源代码以找出问题所在。对于以下示例,我使用此目录结构:
D:\Root\
|- Child\
| |- Grandchild\
| | |- Grandchild.jpg
| | |- Grandchild.txt
| |- Child.html
| |- Child.txt
|- Root.txt
并导入以下命名空间:
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Enumeration;
示例 1:递归列出所有文件和子目录
var enumeration = new FileSystemEnumerable<FileSystemInfo>(
@"D:\Root",
// What's returned here has to match the generic type
// passed in when creating the FileSystemEnumerable.
// As DirectoryInfo inherits from FileSystemInfo, we
// can use FileSystemInfo for both directories and files.
(ref FileSystemEntry entry) => entry.ToFileSystemInfo(),
// Should be self-explanatory.
new EnumerationOptions() { RecurseSubdirectories = true })
{
// We want to include everything: all directories and files.
ShouldIncludePredicate = (ref FileSystemEntry entry) => true
};
作为FileSystemEnumerable<T>
implements IEnumerable<T>
,对于我们的示例,这是一个迭代集合的情况FileSystemInfo
- 这里没有什么特别的:
foreach (var item in enumeration)
{
Console.WriteLine($"{item.FullName} - {item.LastAccessTime}");
}
打印:
D:\Root\Child - 03/10/2020 18:34:16
D:\Root\Root.txt - 03/10/2020 17:39:54
D:\Root\Child\Child.html - 03/10/2020 18:27:20
D:\Root\Child\Child.txt - 03/10/2020 17:40:15
D:\Root\Child\Grandchild - 03/10/2020 18:44:36
D:\Root\Child\Grandchild\Grandchild.jpg - 03/10/2020 18:44:28
D:\Root\Child\Grandchild\Grandchild.txt - 03/10/2020 17:40:10
你会注意到几件事:
- 即使在递归时,从调用者的角度来看,它也是一个扁平结构
- 结果似乎首先按字母顺序按子目录排序,然后按字母顺序按文件名排序
示例 2:递归列出所有子目录
// We're returning strings this time.
var enumeration = new FileSystemEnumerable<string>(
@"D:\Root",
// Returns the full path to the directory.
(ref FileSystemEntry entry) => entry.ToFullPath(),
new EnumerationOptions() { RecurseSubdirectories = true })
{
// Only include directories in the result set.
ShouldIncludePredicate = (ref FileSystemEntry entry) => entry.IsDirectory
};
运行这个:
foreach (var item in enumeration)
{
Console.WriteLine(item);
}
印刷:
D:\Root\Child
D:\Root\Child\Grandchild
示例 3:按扩展名过滤文件
var extensions = new List<string> { ".html", ".jpg" };
// Back to using FileSystemInfo.
var enumeration = new FileSystemEnumerable<FileSystemInfo>(
@"D:\Root",
(ref FileSystemEntry entry) => entry.ToFileSystemInfo(),
new EnumerationOptions() { RecurseSubdirectories = true })
{
ShouldIncludePredicate = (ref FileSystemEntry entry) =>
{
// Skip directories.
if (entry.IsDirectory)
{
return false;
}
foreach (string extension in extensions)
{
var fileExtension = Path.GetExtension(entry.FileName);
if (fileExtension.EndsWith(extension, StringComparison.OrdinalIgnoreCase))
{
// Include the file if it matches one of our extensions.
return true;
}
}
// Doesn't match, so exclude it.
return false;
}
};
运行这个:
foreach (var item in enumeration)
{
Console.WriteLine(item.FullName);
}
印刷:
D:\Root\Child\Child.html
D:\Root\Child\Grandchild\Grandchild.jpg
示例 4:从递归中排除某些目录
我刚刚找到另一个代表,它控制递归行为。假设我们修改原始目录结构以包含一个新目录,其中包含我们想要忽略的文件:
D:\Root\
|- Child\
| |- Grandchild\
| | |- Grandchild.jpg
| | |- Grandchild.txt
| |- GrandchildIgnore\
| | |- GrandchildIgnore.txt
| |- Child.html
| |- Child.txt
|- Root.txt
要获取所有其他文件的列表,同时忽略新目录中的文件,我们可以设置ShouldRecursePredicate
:
var enumeration = new FileSystemEnumerable<FileSystemInfo>(
@"D:\Root",
(ref FileSystemEntry entry) => entry.ToFileSystemInfo(),
new EnumerationOptions() { RecurseSubdirectories = true })
{
ShouldIncludePredicate = (ref FileSystemEntry entry) => !entry.IsDirectory,
// If the directory's name ends with ignore, skip it.
ShouldRecursePredicate = (ref FileSystemEntry entry) => !entry.ToFullPath().EndsWith("Ignore", StringComparison.OrdinalIgnoreCase))
};
运行这个:
foreach (var item in enumeration)
{
Console.WriteLine(item.FullName);
}
印刷:
D:\Root\Root.txt
D:\Root\Child\Child.html
D:\Root\Child\Child.txt
D:\Root\Child\Grandchild\Grandchild.jpg
D:\Root\Child\Grandchild\Grandchild.txt
如我们所愿,不包括目录。
示例 5:获取文件的长度
var enumeration = new FileSystemEnumerable<(long, string)>(
@"D:\Root",
(ref FileSystemEntry entry) => (entry.Length, entry.FileName.ToString()))
{
ShouldIncludePredicate = (ref FileSystemEntry entry) => !entry.IsDirectory
};
给定 1D:\Root
个 122 字节的文件,运行:
foreach (var (length, fileName) in enumeration)
{
Console.WriteLine($"Name: {fileName} Length: {length}");
}
印刷:
Name: Root.txt Length: 122
推荐阅读
- java - 如何修复错误“无法编译的源代码 - 错误的树类型:ViewVotesPanel”
- python - 无法在 python 中加载 skmisc.loess
- knn - 多分类中的满分?
- reactjs - 我想在单击删除图标时删除特定组件。我怎样才能做到这一点?
- django - Django TypeError - TypeError: issubclass() arg 1 必须是一个类
- aws-lambda - AWS ECS Fargate 不带负载均衡器用于内部服务
- c# - 一起使用 Unity 和 Node.js 服务器时出现“MulterError: Unexpected field”
- python - Serverless 在 Conda 虚拟环境中找不到我的 AWS 凭证是否有原因?
- report - 生成仅包含提取字段的 Splunk 报告
- amazon-web-services - 删除 CloudFormation 中不可操作的堆栈集