【问题标题】:Retrieve a list of filenames in folder and all subfolders quickly快速检索文件夹和所有子文件夹中的文件名列表
【发布时间】:2012-05-16 00:35:55
【问题描述】:

我需要获取所有 Word 文档的列表。 *.doc 和 *.docx 存储在基于 Windows 的文件夹中,包含许多子文件夹和子子文件夹等...

Searching for a file with C# 有一个有效的答案,它已有 2 年历史,搜索 1500 个文件需要 10 秒,(将来可能会有 10,000 个或更多)。我将发布我的代码,该代码基本上是上述链接的副本。谁有更好的解决方案?

DateTime dt = DateTime.Now;
DirectoryInfo dir = new DirectoryInfo(MainFolder);
List<FileInfo> matches = 
          new List<FileInfo>(dir.GetFiles("*.doc*",SearchOption.AllDirectories));
TimeSpan ts = DateTime.Now-dt;
MessageBox.Show(matches.Count + " matches in " + ts.TotalSeconds + " seconds");

【问题讨论】:

  • 而不是 List 写入字典。它很快。否则我认为你的速度最快。
  • @RobertLevy:他自己给出了那个链接。
  • @RobertLevy wow 在评论之前阅读问题,我在我的问题中引用了该确切链接
  • 也许这个链接会对你有所帮助:stackoverflow.com/questions/7865159/…

标签: c# winforms


【解决方案1】:

您可以使用Directory.EnumerateFiles 代替GetFiles。这样做的好处是将文件作为 IEnumerable&lt;T&gt; 返回,这使您可以立即开始处理结果集(而不是等待返回整个列表)。

如果您只是在计算文件数量或列出所有文件,则可能无济于事。但是,如果您可以对结果进行处理和/或过滤,尤其是如果您可以在其他线程中执行任何操作,则速度会明显加快。

来自文档:

EnumerateFiles 和 GetFiles 方法的区别如下: 使用 EnumerateFiles 时,可以在返回整个集合之前开始枚举名称集合;当您使用 GetFiles 时,您必须等待返回整个名称数组,然后才能访问该数组。因此,当您处理许多文件和目录时,EnumerateFiles 会更高效。

【讨论】:

  • 我只是列出文件名。这听起来很有希望,因为我可以在它搜索时添加到列表中,这样至少程序不会冻结。我需要在后台工作人员中运行它吗?
  • @K'Leg 是的 - 如果你想防止程序冻结,我会用它在后台线程中制作文件“块”,然后一次编组一个块(添加到您的显示)返回到 UI 线程。 (逐项执行可能会导致它运行得比现在更慢......)
  • 虽然有 1500 个左右的文件,但我只希望它返回 5 到 50 个,如果达到 200 个,我打算停止搜索。
  • @K'Leg 在这种情况下,使用 EnumerateFiles 会更好,因为您可以在中途停止枚举;)
【解决方案2】:

怀疑你可以做很多事情,

dir.GetFiles("*.doc|*.docx", SearchOptions.AllDirectories) 可能会产生影响,因为它是更具限制性的模式。

【讨论】:

  • 使用 1 个过滤器或两者都需要完全相同的时间,但是谢谢我现在知道如何请求过滤器
【解决方案3】:

如果你想要除了making sure the Windows Indexing Service is enable on the target folders 之外的完整列表,其实不是。您的主要延迟将从硬盘驱动器读取,并且没有优化您的 C# 代码将使该过程更快。您可以创建自己的简单索引服务,也许使用FileSystemWatcher,无论添加多少文档,它都会给您亚秒级的响应时间。

【讨论】:

    【解决方案4】:

    我建议您第一次使用 StopWatch 而不是 DateTime 来获取经过的时间。
    第二次为了让您的搜索更快,您不应该将 GetFiles 的结果存储在列表中,而是直接存储到数组中。
    最后,您应该优化您的搜索模式:您想要每个 doc 和 docx 文件,尝试 "*.doc?"
    这是我的建议:

    var sw = new Stopwatch();
    sw.Start();
    
    var matches = Directory.GetFiles(MainFolder, "*.doc?", SearchOption.AllDirectories);
    
    sw.Stop();
    MessageBox.Show(matches.Length + " matches in " + sw.Elapsed.TotalSeconds + " seconds");
    

    【讨论】:

    • 我很欣赏秒表的建议,至于 *.doc 的过滤器选项?它根本没有性能差异,搜索似乎需要相同的时间。什么?做比较 *?
    • 根据 MSDN 文档,* 代表 0 个或多个字符;和 ?正好是零个或一个字符。
    • 很有趣,所以它可能会稍微提高速度,但在我的情况下,我搜索的文件数量并不明显,谢谢。
    猜你喜欢
    • 2022-08-22
    • 2018-07-28
    • 1970-01-01
    • 1970-01-01
    • 2013-01-27
    • 2020-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多