You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何高效合并多组Directory.EnumerateFiles查询获取最新指定文件

优化文件筛选逻辑:高效获取符合规则的最新文件

需求概述

从指定目录中获取3个符合特定规则的最新文件:

  • 文件名包含"red"且不以"H"开头
  • 文件名包含"red"且以"H"开头
  • 文件名包含"blue"且不以"H"开头
    当前代码可正常运行,但多次调用Directory.EnumerateFiles导致IO效率偏低,需优化实现方式。

当前可运行代码

string orderNum = "123465";

string[] s1 = Directory.EnumerateFiles(pathSetting, "*" + orderNum+ "*.txt", SearchOption.AllDirectories)
                       .Where(name => name.Contains("red") && !name.StartsWith("H"))
                       .OrderByDescending(file => new FileInfo(file).LastWriteTime)
                       .ToArray();

string[] s2 = Directory.EnumerateFiles(pathSetting, "*" + orderNum+ "*.txt", SearchOption.AllDirectories)
                       .Where(name => name.Contains("red") && name.StartsWith("H"))
                       .OrderByDescending(file => new FileInfo(file).LastWriteTime)
                       .ToArray();

string[] s3 = Directory.EnumerateFiles(pathSetting, "*" + orderNum+ "*.txt", SearchOption.AllDirectories)
                       .Where(name => name.Contains("blue") && !name.StartsWith("H"))
                       .OrderByDescending(file => new FileInfo(file).LastWriteTime)
                       .ToArray();

int sourceArrayLength = (s1.Length > 0 ? 1 : 0) +
                        (s2.Length > 0 ? 1 : 0) +
                        (s3.Length > 0 ? 1 : 0);

string[] sourceFiles = new string[sourceArrayLength];
int arrayCount = 0;
if (s1.Length > 0)
{
  sourceFiles[arrayCount] = s1[0];
  arrayCount++;
}

if (s2.Length > 0)
{
  sourceFiles[arrayCount] = s2[0];
  arrayCount++;
}

if (s3.Length > 0)
{
  sourceFiles[arrayCount] = s3[0];
  arrayCount++;
}

// perform action on the files

尝试的错误代码及问题

string[] sFull = Directory.EnumerateFiles(pathSetting, "*" + orderNum+ "*.txt", SearchOption.AllDirectories)
                          .First(name => name.Contains("red") && name.StartsWith("H"))
                          .OrderByDescending(file => new FileInfo(file).LastWriteTime)
         .Concat(Directory.EnumerateFiles(pathSetting, "*" + orderNum+ "*.txt", SearchOption.AllDirectories)
                          .First(name => name.Contains("red") && !name.StartsWith("H"))
                          .OrderByDescending(file => new FileInfo(file).LastWriteTime))
         .Concat(Directory.EnumerateFiles(pathSetting, "*" + orderNum+ "*.txt", SearchOption.AllDirectories)
                          .First(name => name.Contains("blue") && !name.StartsWith("H"))
                          .OrderByDescending(file => new FileInfo(file).LastWriteTime))
         .ToArray();

错误原因:First()返回单个字符串而非可枚举集合,无法直接调用OrderByDescending,导致编译失败。

优化方案

核心思路:仅遍历目录一次,提前获取文件写入时间以避免重复IO操作,再按规则筛选各组最新文件。

优化代码

string orderNum = "123465";
var searchPattern = $"*{orderNum}*.txt";

// 一次性遍历目录,获取符合通配符的文件路径及写入时间
var allFiles = Directory.EnumerateFiles(pathSetting, searchPattern, SearchOption.AllDirectories)
                        .Select(filePath => new 
                        { 
                            Path = filePath, 
                            LastWriteTime = File.GetLastWriteTime(filePath) // 静态方法更高效,无需创建FileInfo实例
                        });

// 定义三个筛选规则
var rules = new List<Func<(string Path, DateTime LastWriteTime), bool>>
{
    f => f.Path.Contains("red") && !f.Path.StartsWith("H"),
    f => f.Path.Contains("red") && f.Path.StartsWith("H"),
    f => f.Path.Contains("blue") && !f.Path.StartsWith("H")
};

// 收集每个规则下的最新文件
var sourceFiles = new List<string>();
foreach (var rule in rules)
{
    var latestFile = allFiles.Where(rule)
                            .OrderByDescending(f => f.LastWriteTime)
                            .FirstOrDefault();
    if (latestFile != null)
    {
        sourceFiles.Add(latestFile.Path);
    }
}

// 后续操作sourceFiles即可
// perform action on the files

优化点说明

  1. 减少IO次数:从3次目录遍历改为1次,大幅提升大目录场景下的效率。
  2. 降低资源消耗:用File.GetLastWriteTime()替代重复创建FileInfo实例,减少内存占用。
  3. 逻辑简洁可维护:通过规则列表统一处理筛选逻辑,避免冗余代码。
  4. 异常安全:用FirstOrDefault()替代First(),无匹配文件时不会抛出异常。

额外建议

  • 若仅需文件名而非完整路径,可在Select中使用Path.GetFileName(filePath)进一步减少内存占用。
  • 针对超大型目录,可使用Directory.EnumerateFilesAsync异步遍历,避免阻塞WebAPI主线程。

内容的提问来源于stack exchange,提问作者FatherOfDiwaffe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 06:45:33