C#使用Directory.EnumerateFiles做多扩展名过滤如何优化性能?
最优实现方案
你只需要把允许的扩展名提前存入哈希集合,单次遍历文件列表完成过滤即可,代码如下:
// 预处理扩展名规则,建议全局仅初始化一次,无需每次查询重复创建 var allowedExtensions = new HashSet<string>( filter.Split('|'), StringComparer.OrdinalIgnoreCase // 适配Windows扩展名不区分大小写的特性 ); var files = Directory.EnumerateFiles(path, "*.*", SearchOption.AllDirectories) .Where(filePath => allowedExtensions.Contains(Path.GetExtension(filePath))) .ToList();
方案优势
- 仅遍历一次文件列表,比多次调用
Directory.EnumerateFiles、或多次遍历文件列表过滤的方案性能高得多,文件数量越大性能优势越明显 - 哈希集合的匹配查询复杂度为O(1),比多次叠加
EndsWith判断的效率更高,允许的扩展名越多优势越突出 - 使用
Path.GetExtension获取文件后缀,比直接用EndsWith更严谨,可避免文件名中间包含匹配后缀导致的误判(例如test.csv.bak不会被误识别为csv文件) - 内置大小写不敏感匹配,避免
.TXT、.Xml这类大小写不统一的后缀被遗漏
你提到的两种写法的问题
- 多次调用
Directory.EnumerateFiles的写法:每次调用都会重新扫描整个目录树,IO开销随扩展名数量成倍增长,性能最差 - 先统一枚举再多次
AddRange的写法:虽然只扫描了一次目录树,但会遍历N次全量文件列表(N为扩展名数量),还可能因为重复的扩展名规则导致同一个文件被多次加入结果列表,额外增加开销,性能远不如单次遍历+哈希集合匹配的方案
内容的提问来源于stack exchange,提问作者Bastien Vandamme
相关产品推荐
相关产品推荐

