7

显然,许多应用程序需要处理文件并向用户显示错误。然而 System.IO.File 类的成员抛出了很多异常。这些仅适用于 ReadAllText:

  • 参数异常
  • 参数NullException
  • 路径过长异常
  • DirectoryNotFoundException
  • IO异常
  • 未授权访问异常
  • FileNotFoundException
  • 不支持异常
  • 安全异常

那么如何在不吞下其他异常的情况下捕获它们并将它们显示给用户呢?

显然,通过完美的编码,您可以消除这两个:

  • 参数异常
  • 参数NullException

如果你写了一个(可能很痛苦的)检查,你可以消除 PathTooLongException。但是,为什么要复制 Microsoft 编写的检查代码呢?

但即使您完成了所有检查,其他异常仍然可能发生:

  • DirectoryNotFoundException
  • IO异常
  • 未授权访问异常
  • FileNotFoundException
  • 不支持异常
  • 安全异常

当您打开文件时,文件和文件夹可能会被删除,安全权限可能会更改等。

除了向用户显示消息外,我看不到在这些情况下您可以做什么。您要查找操作系统找不到的目录吗?修复权限?将代码注入操作系统以支持不受支持的操作?大声笑我所看到的只是显示一条错误消息。

因此,如果我每次打开文件以读取文本时都必须捕获所有这些异常,那么我的代码将不得不冗长且重复,除非我通过捕获 Exception 来吞下异常。

创建一个 FileException 并捕获实际处理文件时可能出现的所有异常是否是一种好习惯?我的想法是这样的:

public class FileException : Exception
{
    public FileException( Exception e )
        : base( e.Message, e.InnerException )
    {
    }
}

public static class FileNoBS
{
    public static string ReadAllText2( string path )
    {
        try
        {
            return File.ReadAllText( path );
        }
        catch ( ArgumentNullException e )
        {
            throw new FileException( e );
        }
        catch ( ArgumentException e )
        {
            throw new FileException( e );
        }
        catch ( PathTooLongException e )
        {
            throw new FileException( e );
        }
        catch ( DirectoryNotFoundException e )
        {
            throw new FileException( e );
        }
        catch ( FileNotFoundException e )
        {
            throw new FileException( e );
        }
        catch ( IOException e )
        {
            throw new FileException( e );
        }
        catch ( UnauthorizedAccessException e )
        {
            throw new FileException( e );
        }
        catch ( NotSupportedException e )
        {
            throw new FileException( e );
        }
        catch ( SecurityException e )
        {
            throw new FileException( e );
        }
    }    
}

然后在捕获异常时,我只需要这样写:

        try
        {
            string text = FileNoBS.ReadAllText2( path );
        }
        catch ( FileException e )
        {
            // display error to user
        }

我真的不明白为什么微软没有以某种方式将所有这些例外归为一类。我错过了什么还是这是一种好习惯?

4

2 回答 2

4

您列出的异常分为两个不同的类别 - 这些表示编码错误,而这些表示运行时问题。您绝对正确,第一类异常是可以预防的:您可以编写代码以使其永远不会发生。例如,如果您的代码null检查了路径,那么您就不会遇到ArgumentNullException调用ReadAllText. 我们来一一分析剩下的异常:

  • IOException, DirectoryNotFoundException,FileNotFoundException - 如果你抓住了,这三个人都会被抓住IOException
  • UnauthorizedAccessException- 应单独捕获
  • NotSupportedException- 可以通过在拨打电话之前验证路径来防止。
  • SecurityException- 可以通过在拨打电话前检查权限来防止。

IOException最后,您可以通过捕获和来覆盖所有指示运行时问题UnauthorizedAccessException的异常,并通过预先验证您计划传递的参数并检查代码的运行时环境来防止其余异常的发生。

于 2013-05-27T10:52:09.973 回答
3

您正在寻找的是System.IO.IOException

System.IO.IOException 的继承层次结构:

System.Object
  System.Exception
    System.SystemException
      System.IO.IOException
        System.IO.DirectoryNotFoundException
        System.IO.DriveNotFoundException
        System.IO.EndOfStreamException
        System.IO.FileLoadException
        System.IO.FileNotFoundException
        System.IO.PathTooLongException
        System.IO.PipeException

ArgumentException 明显地被两个众所周知的异常继承:

System.Object
  System.Exception
    System.SystemException
      System.ArgumentException
        System.ArgumentNullException
        System.ArgumentOutOfRangeException
        //...

一些典型的算术异常:

System.Object
  System.Exception
    System.SystemException
      System.ArithmeticException
        System.DivideByZeroException
        System.NotFiniteNumberException
        System.OverflowException

同样值得注意的是ThreadAbortException,它应该在桌面应用程序中使用的异步事件委托中捕获,或者在重定向/终止 HttpResponse 时也在 ASP.NET 中捕获。

其他异常太基本,无法拥有更多“专门的基本异常”。在System.Exception 的继承层次结构的引用和System.SystemException 的继承层次结构中或通过反射查看它们。

于 2013-05-27T11:00:24.517 回答