ZetCode

C# DirectoryNotFoundException

最后修改于 2025 年 4 月 20 日

本教程解释了如何在 C# 中使用 DirectoryNotFoundException 类来处理目录相关的错误。当文件系统操作期间找不到目录时,会发生此异常。

当目录路径的某部分无效或找不到时,将抛出 DirectoryNotFoundException 类。 它继承自 IOException 并提供有关目录相关故障的特定信息。

DirectoryNotFoundException 帮助区分目录特定的错误和其他 I/O 异常。它通常由 DirectoryDirectoryInfo 和文件相关类中的方法抛出。

DirectoryNotFoundException 基础示例

本示例演示了在尝试访问不存在的目录时捕获 DirectoryNotFoundException。 我们尝试从不存在的目录中获取文件。

Program.cs
using System;
using System.IO;

class Program
{
    static void Main()
    {
        string path = @"C:\NonexistentDirectory";
        
        try
        {
            string[] files = Directory.GetFiles(path);
            Console.WriteLine($"Found {files.Length} files.");
        }
        catch (DirectoryNotFoundException ex)
        {
            Console.WriteLine($"Directory not found: {ex.Message}");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Other error: {ex.Message}");
        }
    }
}

该代码尝试从不存在的目录中获取文件。 当指定的路径无效时,Directory.GetFiles() 会抛出 DirectoryNotFoundException。 异常处理程序会捕获此特定错误并显示有意义的消息。

该示例通过在更一般的异常之前捕获特定的 DirectoryNotFoundException 来展示正确的异常处理。这允许有针对性的错误恢复,同时仍然捕获意外的错误。

检查目录是否存在

此示例演示了在尝试操作之前检查目录是否存在的正确方法,从而防止 DirectoryNotFoundException。

Program.cs
using System;
using System.IO;

class Program
{
    static void Main()
    {
        string path = @"C:\Temp\Reports";
        
        if (Directory.Exists(path))
        {
            try
            {
                string[] files = Directory.GetFiles(path);
                Console.WriteLine($"Found {files.Length} files in directory.");
            }
            catch (UnauthorizedAccessException ex)
            {
                Console.WriteLine($"Access denied: {ex.Message}");
            }
        }
        else
        {
            Console.WriteLine("Directory does not exist. Creating it...");
            Directory.CreateDirectory(path);
            Console.WriteLine("Directory created successfully.");
        }
    }
}

该代码首先使用 Directory.Exists 检查目录是否存在。 如果不存在,则创建目录而不是抛出异常。 这是一种避免 DirectoryNotFoundException 的预防方法。

该示例还展示了如何处理其他潜在的异常,例如 UnauthorizedAccessException。 这通过在操作之前检查条件并处理特定的故障情况来演示防御性编程。

在文件操作中处理 DirectoryNotFoundException

此示例显示了当包含目录不存在时,DirectoryNotFoundException 如何在文件操作期间发生。

Program.cs
using System;
using System.IO;

class Program
{
    static void Main()
    {
        string filePath = @"C:\NonexistentDirectory\data.txt";
        
        try
        {
            using (StreamWriter writer = new StreamWriter(filePath))
            {
                writer.WriteLine("Test data");
            }
            Console.WriteLine("File written successfully.");
        }
        catch (DirectoryNotFoundException ex)
        {
            Console.WriteLine($"Directory not found: {ex.Message}");
            Console.WriteLine("Creating directory structure...");
            
            Directory.CreateDirectory(Path.GetDirectoryName(filePath));
            Console.WriteLine("Directory created. Try again.");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error: {ex.Message}");
        }
    }
}

该代码尝试写入不存在的目录中的文件。 当父目录不存在时,StreamWriter 构造函数会抛出 DirectoryNotFoundException。 处理程序捕获此异常并创建目录。

此示例演示了通过自动创建丢失的目录结构来进行错误处理和恢复。 它展示了如何使用 Path.GetDirectoryName 从文件路径中提取目录路径。

DirectoryInfo 中的 DirectoryNotFoundException

本示例演示了使用 DirectoryInfo 类访问不存在的目录时出现的 DirectoryNotFoundException。

Program.cs
using System;
using System.IO;

class Program
{
    static void Main()
    {
        string path = @"C:\NonexistentDirectory";
        DirectoryInfo dirInfo = new DirectoryInfo(path);
        
        try
        {
            Console.WriteLine($"Directory attributes: {dirInfo.Attributes}");
            Console.WriteLine($"Last write time: {dirInfo.LastWriteTime}");
        }
        catch (DirectoryNotFoundException ex)
        {
            Console.WriteLine($"Directory not found: {ex.Message}");
            Console.WriteLine($"Attempted path: {ex.Message.Split('\'')[1]}");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error: {ex.Message}");
        }
    }
}

DirectoryInfo 构造函数不会立即抛出异常,但当目录不存在时,访问诸如 Attributes 之类的属性会抛出异常。 此行为与静态 Directory 方法不同。

该示例展示了如何从异常消息中提取信息,并演示了 DirectoryInfo 属性的延迟求值特性。 了解 Directory 和 DirectoryInfo 之间的这种差异非常重要。

使用异常处理进行递归目录处理

本示例展示了在递归处理目录时如何处理 DirectoryNotFoundException,这可能会遇到无效路径。

Program.cs
using System;
using System.IO;

class Program
{
    static void ProcessDirectory(string path)
    {
        try
        {
            foreach (string dir in Directory.GetDirectories(path))
            {
                ProcessDirectory(dir);
            }
            
            Console.WriteLine($"Processing: {path}");
            // Process files here
        }
        catch (DirectoryNotFoundException ex)
        {
            Console.WriteLine($"Skipping directory: {path} - {ex.Message}");
        }
        catch (UnauthorizedAccessException ex)
        {
            Console.WriteLine($"Access denied: {path} - {ex.Message}");
        }
    }

    static void Main()
    {
        string rootPath = @"C:\SomeDirectory";
        ProcessDirectory(rootPath);
    }
}

递归目录处理器包括针对 DirectoryNotFoundException 和其他常见目录访问错误的特定处理。 这允许即使某些目录不可访问,处理也能继续。

这种模式对于需要能够应对部分故障的实际应用程序非常有用。 该示例展示了如何使用全面的错误处理来构建递归处理。

多线程环境中的 DirectoryNotFoundException

本示例演示了在多线程场景中处理 DirectoryNotFoundException,在这种场景中,目录可能被另一个线程删除。

Program.cs
using System;
using System.IO;
using System.Threading;

class Program
{
    static void Worker(object path)
    {
        string dirPath = (string)path;
        
        try
        {
            for (int i = 0; i < 5; i++)
            {
                string[] files = Directory.GetFiles(dirPath);
                Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId}: Found {files.Length} files");
                Thread.Sleep(1000);
            }
        }
        catch (DirectoryNotFoundException)
        {
            Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId}: Directory removed during processing");
        }
    }

    static void Main()
    {
        string tempPath = Path.Combine(Path.GetTempPath(), "TempScan");
        Directory.CreateDirectory(tempPath);
        
        // Create some test files
        for (int i = 0; i < 3; i++)
        {
            File.Create(Path.Combine(tempPath, $"file{i}.tmp")).Close();
        }
        
        // Start worker threads
        Thread worker1 = new Thread(Worker);
        Thread worker2 = new Thread(Worker);
        worker1.Start(tempPath);
        worker2.Start(tempPath);
        
        // Simulate directory removal
        Thread.Sleep(2000);
        try
        {
            Directory.Delete(tempPath, true);
            Console.WriteLine("Main thread: Directory deleted");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Main thread: {ex.Message}");
        }
        
        worker1.Join();
        worker2.Join();
    }
}

该示例创建一个临时目录并启动多个线程来处理它。 然后,主线程在工作线程仍在活动时删除该目录。 工作线程可以优雅地处理 DirectoryNotFoundException。

这演示了在多线程文件系统操作中可能发生的竞争条件。 该示例展示了针对此类场景的可靠错误处理,这在实际应用程序中很常见。

自定义 DirectoryNotFoundException 处理

此示例展示了如何创建一个自定义方法,该方法使用特定的 DirectoryNotFoundException 处理和恢复来包装目录操作。

Program.cs
using System;
using System.IO;

class DirectoryHelper
{
    public static void SafeDirectoryOperation(string path, Action<string> operation)
    {
        int attempts = 0;
        const int maxAttempts = 2;
        
        while (attempts < maxAttempts)
        {
            try
            {
                operation(path);
                return;
            }
            catch (DirectoryNotFoundException)
            {
                attempts++;
                if (attempts >= maxAttempts)
                {
                    Console.WriteLine($"Directory not found after {maxAttempts} attempts");
                    throw;
                }
                
                Console.WriteLine("Directory not found. Attempting to create...");
                Directory.CreateDirectory(path);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error: {ex.Message}");
                throw;
            }
        }
    }
}

class Program
{
    static void Main()
    {
        string path = @"C:\Temp\CustomDirectory\Reports";
        
        try
        {
            DirectoryHelper.SafeDirectoryOperation(path, dirPath =>  
            {
                string[] files = Directory.GetFiles(dirPath);
                Console.WriteLine($"Found {files.Length} files");
            });
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Operation failed: {ex.Message}");
        }
        
        // Test with file creation
        string filePath = Path.Combine(path, "data.txt");
        DirectoryHelper.SafeDirectoryOperation(Path.GetDirectoryName(filePath), dirPath =>  
        {
            using (StreamWriter writer = new StreamWriter(filePath))
            {
                writer.WriteLine("Test data");
            }
            Console.WriteLine("File created successfully");
        });
    }
}

SafeDirectoryOperation 方法提供了一个可重用的模式,用于处理 DirectoryNotFoundException 并自动恢复。 它尝试执行操作,如果缺少目录则创建目录,然后重试。

此示例演示了高级异常处理模式,包括重试逻辑和高阶函数。 自定义方法可以在应用程序中重用,以实现一致的目录操作处理。

来源

DirectoryNotFoundException 类文档

本教程介绍了使用 DirectoryNotFoundException 在 C# 中处理目录相关的错误,包括预防、处理和恢复模式。

作者

我的名字是 Jan Bodnar,我是一位充满热情的程序员,拥有丰富的编程经验。 我自 2007 年以来一直撰写编程文章。到目前为止,我已经撰写了超过 1,400 篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有 C# 教程