Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/259.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/solr/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 快速估计子文件夹的数量_C#_Getdirectories - Fatal编程技术网

C# 快速估计子文件夹的数量

C# 快速估计子文件夹的数量,c#,getdirectories,C#,Getdirectories,我的C#3.0应用程序应该遍历文件夹并在其中执行一些操作。为了显示有意义的进展,我需要知道文件夹总数 如果我使用Directory.GetDirectories和AllDirectories选项,这将在我的2Tb硬盘上花费很长时间,其中包含大约100K个文件夹,即使是这个操作,我也应该给出一个进度!我能做的唯一有意义的事情就是使用recursiveDirectory.GetDirectories,并向用户提供一些已经找到的目录。然而,这比第一种方法需要更长的时间 我认为,这两种方法都太慢了。有没

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

如果我使用
Directory.GetDirectories
AllDirectories
选项,这将在我的2Tb硬盘上花费很长时间,其中包含大约100K个文件夹,即使是这个操作,我也应该给出一个进度!我能做的唯一有意义的事情就是使用recursive
Directory.GetDirectories
,并向用户提供一些已经找到的目录。然而,这比第一种方法需要更长的时间


我认为,这两种方法都太慢了。有没有办法更快地得到这个号码?例如,使用
PInvoke
从一些文件表中获取数据?还有其他想法吗?

我的建议是,在获取所有目录时,只需向用户显示一个无限滚动的进度条,并且只在应用程序执行工作时向用户显示实际进度


这样,当一切发生时,用户将知道应用程序正在后台工作。

浏览和使用API。我认为在您的情况下,它们的工作速度会更快

如果您实施此功能,您会发现您的第一次预扫描速度最慢,但它会加快下一次(完整)扫描,因为文件夹结构正在缓存

可以选择仅统计前N(2..4)个级别中的文件夹。这可能仍然缓慢,但它将允许估计的进展。只要假设所有较低级别都包含相同数量的文件


第2部分,关于p/p问题

这里的主要成本是真正的低级别I/O,任何API的开销都可以忽略不计


GetFiles()
替换为
EnumerateFiles()
(Fx4)可能会使您受益匪浅。对于主循环而言,比预扫描更重要。

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

我写了一个非常简单的文件枚举。该过程在数学上是连续的,即无论发生什么情况,它都不会在以后变为较低的值。这个估计是基于所有文件夹都拥有相同数量的文件和子文件夹的想法,这显然不是事实,但它足以得到一个合理的想法

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

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);
        }
    }
}
公共静态IEnumerable枚举文件(字符串根)
{
var files=Directory.GetFiles(根目录);
var dirs=Directory.GetDirectories(根目录);
var fact=1f/(float)(dirs.Length+1);//这是一个粗略的估计
for(int i=0;i
谢谢你的评论,贾斯汀。这是解决问题的简单方法。但是,正如您所知,Microsoft指南建议避免无限进度条。知道有多少工作落后总是好的。@Alex-只有在知道工作量的情况下,你才能显示有限的进展。当你不确定的时候,我宁愿看到一个无限的进度条而不是一个完全错误的。“亚历克斯,考虑到Windows在显示一个删除文件的数量时显示了无限的进度条。指导方针不是硬性规定。在这种情况下,我认为您可以理解以下Windows(Windows?Windows?)示例。好吧,工作量是众所周知的-以当前文件夹为例,除以文件夹总数,然后乘以100。显示确切的进度没有问题,除了文件夹总数很慢。@Greg-我同意,但这个解决方案比回答我的问题更“放弃”。我仍然希望有一些快速的技巧。是的,但是即使这样,如果不遍历整个树,你也不知道目录的数量,这是很慢的部分。好主意-Win API有时真的比.NET更快。然而,我想知道在某些NTFS/FAT表中是否已经存在这样一个数字,因为它们将以本机方式运行,并且很可能目录类本身将使用类似的东西。不过我不确定。我不相信这有多大帮助,因为.NET已经相当优化,而且几乎可以直接访问Win32 API。无论哪种方式,都存在上下文切换,因此这可能不会对性能产生太大影响。此外,这对大型目录树也没有帮助。谢谢-这正是我的想法。如果我找不到任何其他选项,我会选择这种方法(任何从神奇的地方快速提取数字的神奇方法)。Alex:文件系统不存储您想要的信息,所以找到它的唯一方法是扫描。感谢您的评论-这与Gabe已经给出的一样,也是我考虑过的。