C# Language Utilisation de la récursivité pour obtenir l'arborescence de répertoires


Exemple

L'une des utilisations de la récursivité consiste à naviguer dans une structure de données hiérarchique, telle qu'une arborescence de répertoires de systèmes de fichiers, sans connaître le nombre de niveaux de l'arborescence ni le nombre d'objets sur chaque niveau. Dans cet exemple, vous verrez comment utiliser la récursivité dans une arborescence de répertoires pour rechercher tous les sous-répertoires d'un répertoire spécifié et imprimer l'arborescence complète dans la console.

internal class Program
{
    internal const int RootLevel = 0;
    internal const char Tab = '\t';

    internal static void Main()
    {
        Console.WriteLine("Enter the path of the root directory:");
        var rootDirectorypath = Console.ReadLine();

        Console.WriteLine(
            $"Getting directory tree of '{rootDirectorypath}'");

        PrintDirectoryTree(rootDirectorypath);
        Console.WriteLine("Press 'Enter' to quit...");
        Console.ReadLine();
    }

    internal static void PrintDirectoryTree(string rootDirectoryPath)
    {
        try
        {
            if (!Directory.Exists(rootDirectoryPath))
            {
                throw new DirectoryNotFoundException(
                    $"Directory '{rootDirectoryPath}' not found.");
            }

            var rootDirectory = new DirectoryInfo(rootDirectoryPath);
            PrintDirectoryTree(rootDirectory, RootLevel);
        }
        catch (DirectoryNotFoundException e)
        {
            Console.WriteLine(e.Message);
        }
    }

    private static void PrintDirectoryTree(
        DirectoryInfo directory, int currentLevel)
    {
        var indentation = string.Empty;
        for (var i = RootLevel; i < currentLevel; i++)
        {
            indentation += Tab;
        }

        Console.WriteLine($"{indentation}-{directory.Name}");
        var nextLevel = currentLevel + 1;
        try
        {
            foreach (var subDirectory in directory.GetDirectories())
            {
                PrintDirectoryTree(subDirectory, nextLevel);
            }
        }
        catch (UnauthorizedAccessException e)
        {
            Console.WriteLine($"{indentation}-{e.Message}");
        }
    }
}

Ce code est un peu plus compliqué que le strict minimum pour effectuer cette tâche, car il inclut la vérification des exceptions pour gérer les problèmes liés à l'obtention des répertoires. Vous trouverez ci-dessous une ventilation du code en segments plus petits avec des explications sur chacun.

Main :

La méthode principale prend une entrée d'un utilisateur sous forme de chaîne, qui doit être utilisée comme chemin d'accès au répertoire racine. Il appelle ensuite la méthode PrintDirectoryTree avec cette chaîne comme paramètre.

PrintDirectoryTree(string) :

C'est la première des deux méthodes qui gèrent l'impression de l'arborescence de répertoires. Cette méthode prend en paramètre une chaîne représentant le chemin d'accès au répertoire racine. Il vérifie si le chemin est un répertoire réel et, sinon, lève une exception DirectoryNotFoundException qui est ensuite traitée dans le bloc catch. Si le chemin est un répertoire réel, un DirectoryInfo objet rootDirectory est créé à partir du chemin d' accès, et le second PrintDirectoryTree méthode est appelée avec le rootDirectory objet et RootLevel , qui est un nombre entier constant avec une valeur de zéro.

PrintDirectoryTree(DirectoryInfo, int) :

Cette seconde méthode traite le plus gros du travail. Il prend un DirectoryInfo et un entier comme paramètres. DirectoryInfo est le répertoire en cours et l'entier est la profondeur du répertoire par rapport à la racine. Pour faciliter la lecture, la sortie est en retrait pour chaque niveau de profondeur du répertoire en cours, de sorte que la sortie ressemble à ceci:

-Root
    -Child 1
    -Child 2
        -Grandchild 2.1
    -Child 3

Une fois le répertoire en cours imprimé, ses sous-répertoires sont récupérés, et cette méthode est ensuite appelée sur chacun d'eux avec une valeur de niveau de profondeur supérieure au courant. Cette partie est la récursivité: la méthode elle-même. Le programme s'exécutera de cette manière jusqu'à ce qu'il ait visité tous les répertoires de l'arborescence. Lorsqu'il atteint un répertoire sans sous-répertoires, la méthode est automatiquement renvoyée.

Cette méthode intercepte également une UnauthorizedAccessException , qui est lancée si l'un des sous-répertoires du répertoire en cours est protégé par le système. Le message d'erreur est imprimé au niveau d'indentation actuel pour la cohérence.

La méthode ci-dessous propose une approche plus simple de ce problème:

internal static void PrintDirectoryTree(string directoryName)
{
    try
    {
        if (!Directory.Exists(directoryName)) return;
        Console.WriteLine(directoryName);
        foreach (var d in Directory.GetDirectories(directoryName))
        {
            PrintDirectoryTree(d);
        }
    }
    catch (Exception e)
    {
        Console.WriteLine(e.Message);
    }
}

Cela n'inclut pas la vérification d'erreur spécifique ou le formatage de sortie de la première approche, mais cela fait effectivement la même chose. Comme il n'utilise que des chaînes contrairement à DirectoryInfo , il ne peut pas donner accès à d'autres propriétés de répertoire telles que les autorisations.