【问题标题】:Writing List<String> of Directories with Subdirectories使用子目录编写目录列表<String>
【发布时间】:2015-08-29 23:21:22
【问题描述】:

现在,我知道 Stackoverflow 上已经有很多关于文件夹递归和获取文件夹(包括它的子目录等)的问题,但我没有找到与我在这里遇到的任何相关的任何问题。

我的问题如下:

我从here(页面底部)获取了关于文件夹递归的代码 sn-p 并根据我的需要进行了调整;也就是说,让它不将所有(子)目录写入控制台,而是让它将它们添加到列表中。这是我的代码(注意被注释掉的部分):

private static List<String> ShowAllFoldersUnder(string path)
{
   var folderList = new List<String>();
   try
   {
      if ((File.GetAttributes(path) & FileAttributes.ReparsePoint)
         != FileAttributes.ReparsePoint)
      {
         foreach (string folder in Directory.GetDirectories(path))
         {
            folderList.Add(folder);
            // Console.WriteLine(folder);
            ShowAllFoldersUnder(folder);
         }
      }
   }
   catch (UnauthorizedAccessException) { }
   return folderList;
}

这就是我所说的(Dir 是包含路径的string):

var _folders = ShowAllFoldersUnder(Dir);
foreach (string folder in _folders)
{
    Console.WriteLine(folder);
}

问题是只有第一级文件夹被添加到列表中,这意味着我的输出例如:

[...]
C:\Users\Test\Pictures
C:\Users\Test\Recent
C:\Users\Test\Saved Games
C:\Users\Test\Searches
C:\Users\Test\SendTo
[...]

如果我从该方法中取消注释 Console.WriteLine(folder);,它会将所有(子)目录回显到控制台:

[...]
C:\Users\Test\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch\User Pinned
C:\Users\Test\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch\User Pinned\ImplicitAppShortcuts
C:\Users\Test\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar
C:\Users\Test\AppData\Roaming\Microsoft\Internet Explorer\UserData
C:\Users\Test\AppData\Roaming\Microsoft\Internet Explorer\UserData\Low
C:\Users\Test\AppData\Roaming\Microsoft\MMC
C:\Users\Test\AppData\Roaming\Microsoft\Network
[...]

在花了数小时研究可能是我的错误之后,我感到绝望。有人知道是什么导致了我的问题吗?

【问题讨论】:

    标签: c# .net list recursion directory


    【解决方案1】:

    ShowAllFoldersUnder 方法返回一个字符串列表,但您真正使用它的唯一一次是在“main”方法中,您将它们写入Console

    你需要改变

    ShowAllFoldersUnder(folder);
    

    folderList.AddRange(ShowAllFoldersUnder(folder));
    

    【讨论】:

    • 给我一个广泛的提示。不知道我是怎么错过的。谢谢!
    • 这会创建很多中间列表。
    【解决方案2】:

    您似乎没有对在递归调用ShowAllFoldersUnder 中找到的文件夹执行任何操作。

    这个修改应该可以解决它。变化:

    ShowAllFoldersUnder(folder);
    

    到:

    folderList.AddRange(ShowAllFoldersUnder(folder));
    

    在生产代码中,我可能会将其重构为在整个递归过程中使用单个 List,以避免创建和合并多个列表的任何开销。

    【讨论】:

    • 这会创建很多中间列表。
    • @dotctor 我的答案是正确(你很清楚代码不是我的 OP);你的答案更好。这就是为什么我赞成你的回答。
    • 你的回答很好,这也是我投赞成票的原因。
    • @dotctor 太好了,谢谢。你认为我应该修改我的答案还是保持原样?当然是速度类型的。在生产中,我会重构为更像你的。
    • 您应该尽可能地改进您的答案,以供社区中的其他人进一步使用。阅读本文了解更多详情stackoverflow.com/help/answering
    【解决方案3】:

    将你的方法修改为这个

    private static void ShowAllFoldersUnder(string path, List<string> folderList)
    {
       try
       {
          if ((File.GetAttributes(path) & FileAttributes.ReparsePoint)
             != FileAttributes.ReparsePoint)
          {
             foreach (string folder in Directory.GetDirectories(path))
             {
                folderList.Add(folder);
                // Console.WriteLine(folder);
                ShowAllFoldersUnder(folder, folderList);
             }
          }
       }
       catch (UnauthorizedAccessException) { }
    }
    

    现在这样称呼它

    var _folders = new List<string>();
    ShowAllFoldersUnder(Dir, _folders);
    

    这样可以防止其他答案中的许多列表创建和内存消耗。通过使用这种方式,您向该方法提供了一个初始列表,它将向其中添加所有条目,但其他答案每次都会生成一个列表,然后将结果复制到上层列表,这将导致大量内存分配,复制和释放。

    【讨论】:

    • 您对内存消耗的看法是正确的。非常感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 2014-07-14
    • 1970-01-01
    • 2017-05-13
    • 1970-01-01
    • 1970-01-01
    • 2012-01-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多