【问题标题】:Get maximum directorydepth获取最大目录深度
【发布时间】:2016-03-04 11:24:41
【问题描述】:

我只是想知道,是否有一种快速解决方案可以获取我的根目录中最深文件夹的级别。

假设我使用“C:\”,那么我需要一个函数来获取根目录中“最深”文件夹的级别数,而无需遍历每个目录。

【问题讨论】:

  • 如果您不想遍历它,您如何知道根驱动器中任何文件夹的最深级别。 (由您自己或 System.IO 中提供的任何函数)?
  • 问题是是否有一个函数可以为我获取它。我需要知道计数。

标签: c# directory subdirectory


【解决方案1】:

最好的办法是递归使用System.IO.DirectoryInfoGetDirectories。一定不要使用SearchOption.AllDirectories,因为那样会 肯定会因安全错误而中断!

static List<string> directories = new List<string>();
        static void GetDirectories(string path)
        {
            try
            {
                foreach (var directory in Directory.GetDirectories(path))
                {
                    var di = new DirectoryInfo(directory);
                    directories.Add(di.FullName);
                    GetDirectories(di.FullName);
                }
            }
            catch (UnauthorizedAccessException uaex) { }
            catch (PathTooLongException ptlex) { }
            catch (Exception ex) { }
        }

static void Main(string[] args)
    {
        var path = @"C:\";

        GetDirectories(path);

        var maxLevel = directories.Max(d => d.Split('\\').Count());
        var deepest = directories.Select(d => new
            {
                Path = d,
                Levels = d.Split('\\').Count()
            })
        .OrderByDescending(d => d.Levels)
        .First();

    }

但是你会遇到PathTooLongException,看看this question如何解决这个问题。

【讨论】:

  • 但这只会让我得到 C:\ 的所有子目录,还是我错了?
  • 等一下,我给你举个例子。
  • 这是我最长的(字符串);,,; C:\Users\OOO\.atom\packages\atom-yeoman\node_modules\tsd\node_modules\update-notifier\node_modules\latest-version\node_modules\package-json\node_modules\got\node_modules\duplexify\node_modules\end- of-stream\node_modules\once\node_modules\wrappy\test
  • KK nice imma 试试这个非常感谢您的努力
  • 很好,递归调用做得很好。还需要一段时间:P
【解决方案2】:

我被PathTooLongException 困扰并想出了这个:

public static class DirectoryEx
{
    static char driveLetter;
    static string longPath;
    static List<string> directories;

    static DirectoryEx()
    {
        longPath = String.Empty;
    }

    private static char GetAvailableDrive()
    {
        var all = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray().Reverse();
        var occupied = DriveInfo.GetDrives()
            .OrderByDescending(d => d.Name)
            .Select(d => (char)d.Name.ToUpper().First());

        var free = all.Except(occupied).First();

        return free;
    }

    public static List<string> GetDirectories(string path)
    {
        directories = new List<string>();

        // recursive call
        FindDirectories(path);

        return directories;
    }

    static void FindDirectories(string path)
    {
        try
        {
            foreach (var directory in Directory.GetDirectories(path))
            {
                var di = new DirectoryInfo(directory);

                if(!String.IsNullOrEmpty(longPath))
                    directories.Add(di.FullName.Replace(driveLetter + ":\\", longPath + "\\"));
                else
                    directories.Add(di.FullName);

                FindDirectories(di.FullName);
            }
        }
        catch (UnauthorizedAccessException uaex) { Debug.WriteLine(uaex.Message); }
        catch (PathTooLongException ptlex)
        {
            Debug.WriteLine(ptlex.Message);

            longPath = path;

            Task t = new Task(new Action(() =>
            {
                CreateVirtualDrive(longPath);
                FindDirectories(driveLetter + ":\\");
                DeleteVirtualDrive();

                longPath = String.Empty;
            }));

            if (!String.IsNullOrEmpty(longPath))
                t.RunSynchronously();
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.Message); 
        }
    }

    static void CreateVirtualDrive(string path)
    {
        driveLetter = GetAvailableDrive();

        Process.Start(new ProcessStartInfo() {
            FileName = "cmd.exe",
            WindowStyle = ProcessWindowStyle.Hidden,
            Arguments = String.Format("/c subst {0}: {1}", driveLetter.ToString(), path)
        });

        while (!DriveInfo.GetDrives().Select(d => d.Name.ToUpper().First()).Contains(driveLetter))
        {
            System.Threading.Thread.Sleep(1);
        }
    }

    static void DeleteVirtualDrive()
    {
        Process.Start(new ProcessStartInfo()
        {
            FileName = "cmd.exe",
            WindowStyle = ProcessWindowStyle.Hidden,
            Arguments = String.Format("/c subst {0}: /D", driveLetter.ToString())
        });

        while (DriveInfo.GetDrives().Select(d => d.Name.ToUpper().First()).Contains(driveLetter))
        {
            System.Threading.Thread.Sleep(1);
        }
    }
}

用作var directories = DirectoryEx.GetDirectories("C:\\");

这将为每个太长的路径创建一个虚拟驱动器(使用SUBST),因此它仍然可以遍历它。需要优化,可以扩展以提供一些DirectoryInfo 包装类。

【讨论】:

  • 哇,干得好:D甚至不知道这样的事情是可能的:P
  • 不客气,它是一次性写的,所以你可能想看看你是否可以改进它! ;)
猜你喜欢
  • 2013-06-26
  • 1970-01-01
  • 2016-07-15
  • 2022-01-13
  • 1970-01-01
  • 1970-01-01
  • 2020-03-14
  • 1970-01-01
  • 2021-10-11
相关资源
最近更新 更多