使用遞迴獲取目錄樹
遞迴的一個用途是導航分層資料結構,如檔案系統目錄樹,而不知道樹有多少級別或每個級別上的物件數。在此示例中,你將看到如何在目錄樹上使用遞迴來查詢指定目錄的所有子目錄,並將整個樹列印到控制檯。
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}");
}
}
}
此程式碼比完成此任務的最低限度更復雜,因為它包括異常檢查以處理獲取目錄的任何問題。你可以在下面找到將程式碼拆分為較小的段,並對每個段進行說明。
Main
:
main 方法將來自使用者的輸入作為字串,該字串用作根目錄的路徑。然後使用此字串作為引數呼叫 PrintDirectoryTree
方法。
PrintDirectoryTree(string)
:
這是處理實際目錄樹列印的兩種方法中的第一種。此方法將表示根目錄路徑的字串作為引數。它檢查路徑是否是實際目錄,如果不是,則丟擲 DirectoryNotFoundException
,然後在 catch 塊中處理。如果路徑是真實目錄,則從路徑建立 DirectoryInfo
物件 rootDirectory
,並使用 rootDirectory
物件和 RootLevel
呼叫第二個 PrintDirectoryTree
方法,RootLevel
是一個值為零的整數常量。
PrintDirectoryTree(DirectoryInfo, int)
:
第二種方法處理工作的主要問題。它需要一個 DirectoryInfo
和一個整數作為引數。DirectoryInfo
是當前目錄,整數是目錄相對於根的深度。為了便於閱讀,輸出將縮排當前目錄的每個級別,以便輸出如下所示:
-Root
-Child 1
-Child 2
-Grandchild 2.1
-Child 3
列印當前目錄後,將檢索其子目錄,然後在每個目錄上呼叫此方法,其深度級別值比當前值大 1。那部分是遞迴:呼叫自身的方法。程式將以這種方式執行,直到它訪問了樹中的每個目錄。當它到達沒有子目錄的目錄時,該方法將自動返回。
此方法還捕獲 UnauthorizedAccessException
,如果當前目錄的任何子目錄受系統保護,則丟擲 UnauthorizedAccessException
。為了一致性,將在當前縮排級別列印錯誤訊息。
下面的方法提供瞭解決此問題的更基本方法:
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);
}
}
這不包括第一種方法的特定錯誤檢查或輸出格式,但它實際上做了同樣的事情。由於它只使用字串而不是 DirectoryInfo
,因此無法訪問其他目錄屬性(如許可權)。