如何在递归爬网目录结构时获得进展?

时间:2013-05-11 17:29:31

标签: c# recursion directory

我有一个函数可以加载给定文件夹中的所有* .txt及其所有子文件夹。我想得到实际的进展(例如15/35加载)。

但我无法想到如何获取目录结构中加载的文件数量,以添加到当前索引。

* a
  * b
     - 1.txt (file in dir b)
  - 1.txt (file in dir a)
  - 2.txt _(index of this file is 3 - one file from dir below, one file in this dir)_

代码:

    public int getFilesInSubfolders(directory)
    {
        int count = 0;

        foreach (subdirectory in directory)
        {
            count += getFilesInSubfolders();
        }

        foreach (txtfile in folderFiles)
        {

            load(txtfile);
            count++;

            updateProgress(actualIndex); // how to get the actual index? e.g. 15/35 loaded, so that 15
        }
        return count;
    }

4 个答案:

答案 0 :(得分:2)

有两种解决方法。

您可以将ref int count传递给每个递归调用。最外面的调用会将count初始化为零。

例如:

public int IterateDirectories(string root)
{
    int count = 0;
    iterateDirectories(root, ref count);
    return count;
}

private void iterateDirectories(string root, ref int count)
{
    foreach (string directory in Directory.EnumerateDirectories(root))
        iterateDirectories(directory, ref count);

    foreach (string file in Directory.EnumerateFiles(root, "*.txt"))
    {
        // load(file);

        ++count;

        // Now count is the actual number of files processed,
        // so you can use it for updateProgress()
    }
}

或者,您可以将整个事物包装在这样的类中:

public sealed class DirectoryIterator
{
    public static int Iterate(string root)
    {
        var iterator = new DirectoryIterator();
        iterator.iterate(root);
        return iterator.count;
    }

    private void iterate(string root)
    {
        foreach (string directory in Directory.EnumerateDirectories(root))
            iterate(directory);

        foreach (string file in Directory.EnumerateFiles(root, "*.txt"))
        {
            // load(file);

            ++count;

            // Now count is the actual number of files processed,
            // so you can use it for updateProgress()
        }
    }

    private int count;

    private DirectoryIterator(){}
}

您可以这样使用:

int count = DirectoryIterator.Iterate("D:\\");

(尽管您可能不关心返回的值。)

您需要修改此代码以用于您的确切目的(它没有您说已经计算过的文件总数,因此您必须为此添加一个字段)。

注意:我已从这两个示例中省略了错误处理。真正的代码必须避免受保护的系统目录。

答案 1 :(得分:0)

我不明白为什么你必须为此使用递归。 Directory.GetFiles有一个方便的重载,它允许你获取所有子文件夹中的所有文件:

public int GetFilesInSubfolders(string directory)
{
    var files = Directory.GetFiles(directory, "*.txt", SearchOption.AllDirectories));
    for (var i = 0; i < files.Length; i++)
    {
        load(files[i]);
        updateProgress(i); 
    }

    return files.Length;
}

答案 2 :(得分:0)

明显的直接解决方案是将其循环两次 - 首先计算文件数,然后使用计数器updateProgress。 为了使其更具可读性,您可以使用Stack<T>数据结构将其从递归中重构,但这是另一个故事。

在您的解释之后确定我假设以下重构。 一旦不使用递归,就会actualIndex

int totalCounter = GetTheTotalTxtFilesNumber();//as you've mentioned you already have it

Stack<Directory> directoryStack = new Stack<Directory>();
  directoryStack.Push(directory);

  int actualIndex = 0;  
  while(directoryStack.Count > 0)
  {
    Dirextory current = directoryStack.Pop();  

    foreach (txtfile in folderFiles)
    {
       load(txtfile);
       actualIndex++;
       updateProgress(actualIndex);//15 out of 35
    }
    foreach (subdirectory in current )
    {
       directoryStack.Push(subdirectory );
    }
  }

答案 3 :(得分:0)

我可以在15/35而不是35部分给你15部分,因为我不知道这部分直到完成。

public int getFilesInSubfolders(directory,int count)     {

    foreach (subdirectory in directory)
    {
       getFilesInSubfolders(subDirectory,count);
    }

    foreach (txtfile in folderFiles)
    {

        load(txtfile);
        count++;

        updateProgress(count); // how to get the actual index? e.g. 15/35 loaded, so that 15
    }
    return count;
}