【问题标题】:Get files from directory and subdirectories quickly order by latest creation date按最新创建日期快速从目录和子目录中获取文件
【发布时间】:2014-08-22 22:21:07
【问题描述】:

我正在寻找一种方法,该方法将采用文件扩展名类型和目录,并返回此目录和按最新创建日期排序的子目录中的所有文件,即最新文件优先。

到目前为止,我已经确定了以下方法,该方法旨在快速,但是是否有更好的方法来执行此操作,我需要它返回 FileInfo 而不是字符串,并按上述方式排序。

public static IEnumerable<string> GetFileList(string fileSearchPattern, string rootFolderPath)
{
Queue<string> pending = new Queue<string>();
pending.Enqueue(rootFolderPath);
string[] tmp;
while (pending.Count > 0)
{
    rootFolderPath = pending.Dequeue();
    tmp = Directory.GetFiles(rootFolderPath, fileSearchPattern);
    for (int i = 0; i < tmp.Length; i++)
    {
        yield return tmp[i];
    }
    tmp = Directory.GetDirectories(rootFolderPath);
    for (int i = 0; i < tmp.Length; i++)
    {
        pending.Enqueue(tmp[i]);
    }
}
}

【问题讨论】:

标签: c# .net


【解决方案1】:

当我研究这个问题空间时,我发现没有fast 方法可以做到这一点。原因是无论您采用哪种方法,最终都必须转到操作系统以获取目录中的文件列表。而且文件系统不会像搜索引擎那样缓存/索引。所以你最终需要自己重新抓取文件系统。

不过,一旦您有了原始信息,您就可以自己编入索引。

【讨论】:

    【解决方案2】:

    以下内容适用于您的目的。您想使用 Directory.EnumerateFiles(...) 来允许文件列表预先使用更少的内存。它只会在您请求时寻找下一个元素,而不是在开始时将整个集合加载到内存中。

    Directory.EnumerateFiles(rootFolderPath, fileSearchPattern, System.IO.SearchOption.AllDirectories).OrderBy(file => new FileInfo(file).CreationTime)
    

    一个额外的考虑。由于您在文件系统中进行了相当盲目的搜索,因此如果您尝试枚举文件并引发异常,它将使枚举器无效,从而导致它在未完成的情况下退出。我已经发布了该问题的解决方案here

    【讨论】:

    • 延迟加载在这方面有帮助吗? OP 正在尝试获取所有文件,因此延迟执行不会在此处产生性能提升。
    • 延迟加载可能不是正确的措辞。使用 EnumerateFiles(...) 使用的内存占用更小,并且通过仅在您实际请求下一个元素时才实际查找来更快地返回。我已经澄清了我的回答以表明这一点。
    【解决方案3】:

    Directory.GetFiles 确实有一个递归搜索的选项。

    以下应该可以工作,虽然我还没有尝试过。

        IEnumerable<FileInfo> GetFileList(string directory, string extension)
        {
            return Directory.GetFiles(directory, "*" + extension, SearchOption.AllDirectories)
                .Select(f => new FileInfo(f))
                .OrderByDescending(f => f.CreationTime);
        } 
    

    【讨论】:

    • 这是一个低效的解决方案,因为 Directory.GetFiles() 将等到它加载完所有文件后才返回。您应该改用 Directory.EnumerateFiles(...)。
    • 通常情况下,我会同意,但我们是按创建时间排序文件,所以无论如何我们可能必须先加载所有文件。
    • 为什么?文件创建时间不会改变,如果您有一个特别大的文件夹结构,您可能会因为将这么多字符串加载到内存中而出现内存不足错误。无论如何,在您请求下一个元素之前,LINQ OrderBy 方法都不会计算。
    • 啊:您已将 FileInfo 创建放在 OrderBy 中:也就是说,确实可以节省内存空间。不幸的是,问题要求返回 FileInfo,因此我的解决方案是:但是,如果将大文件结构作为 FileInfo 加载到内存中是一个问题,那么您的 Matthew 的解决方案将避免这种情况,但您可能需要构建 FileInfo 两次。
    • 您仍然可以将 .Select() 放在那里,这不是节省内存的部分。主要的内存节省来自使用 Directory.EnumerateFiles(...) 而不是 Directory.GetFiles(...)。 Directory.GetFiles(...) 将在执行时立即为集合中的每个文件创建一个字符串实例。 Directory.EnumerateFiles(...) 只会在您请求“下一个”文件时创建一个字符串实例。
    猜你喜欢
    • 2014-03-29
    • 2012-03-11
    • 2014-10-04
    • 2012-03-07
    • 2023-03-23
    • 2021-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多