Quicky估计了许多子文件夹

时间:2011-06-20 16:08:43

标签: c# getdirectories

我的C#3.0应用程序应该遍历文件夹并在其中执行一些操作。为了显示有意义的进展,我需要知道总文件夹数量。

如果我使用带有Directory.GetDirectories选项的AllDirectories,这需要很长时间才能在我的2Tb硬盘上使用大约100K文件夹,我甚至应该为该操作提供进展!我能做的唯一有意义的事情是使用递归Directory.GetDirectories并向用户提供许多已经找到的目录。但是,这比第一种方法需要更长的时间。

我相信,这两种方法都太慢了。有没有办法让这个数字更快?例如。使用PInvoke从某些文件表中获取?还有其他想法吗?

5 个答案:

答案 0 :(得分:2)

我的建议是在获取所有目录时向用户显示无限滚动的进度条,并且只有在应用程序完成工作时向用户显示实际进度时才会显示。

这样一来,当一切都发生时,用户就会知道应用程序正在后台运行。

答案 1 :(得分:1)

如果你实现这个,你会发现你的第一次预扫描是最慢的,但它会加速下一次(完整)扫描,因为文件夹结构正在缓存。

可能只计算前N(2..4)级别的文件夹。这可能仍然很慢,但它将允许估计的进展。假设所有较低级别包含相同数量的文件。


关于P / Invoke问题的第2部分

您的主要成本是真正的低级I / O,(任何)API的开销可以忽略不计。

您可能会因使用GetFiles()(Fx4)替换EnumerateFiles()而受益。主循环比预扫描更多。

答案 2 :(得分:1)

这种事情很难做到。如果您只是想对进度条进行粗略估计,那么您不需要太多粒度,对吧?我建议手动遍历目录树只有一个或两个级别,以确定有多少个第一级和第二级子目录。然后,只要您点击其中一个子目录,就可以更新进度条。这应该给你一个有意义的进度条,而不需要花太多时间来计算。

答案 3 :(得分:0)

浏览FindFirstFileFindNextFile API。我认为他们会在你的情况下更快地工作

答案 4 :(得分:0)

我写了一个非常简单的文件枚举。进展在数学上是连续的,即无论如何都不会在以后变成较低的值。估计是基于所有文件夹都包含相同数量的文件和子文件夹的想法,这显然几乎不是这种情况,但它足以得到一个合理的想法。

几乎没有缓存,特别是没有深层结构,所以这应该与直接枚举一样快。

public static IEnumerable<Tuple<string, float>> EnumerateFiles (string root)
{
    var files = Directory.GetFiles (root);
    var dirs = Directory.GetDirectories (root);
    var fact = 1f / (float) (dirs.Length + 1); // this makes for a rough estimate

    for (int i = 0; i < files.Length; i++) {
        var file = files[i];
        var f = (float) i / (float) files.Length;
        f *= fact;
        yield return new Tuple<string, float> (file, f);
    }

    for (int i = 0; i < dirs.Length; i++) {
        var dir = dirs[i];
        foreach (var tuple in EnumerateFiles (dir)) {
            var f = tuple.Item2;
            f *= fact;
            f += (i + 1) * fact;
            yield return new Tuple<string, float> (tuple.Item1, f);
        }
    }
}