C# 执行文件io时如何正确处理异常

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/86766/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 11:27:20  来源:igfitidea点击:

How to properly handle exceptions when performing file io

提问by Morten Christiansen

Often I find myself interacting with files in some way but after writing the code I'm always uncertain how rubust it actually is. The problem is that I'm not entirely sure how file related operations can fail and, therefore, the best way to handle expections.

我经常发现自己以某种方式与文件进行交互,但在编写代码后,我总是不确定它实际上有多可靠。问题是我不完全确定文件相关操作如何失败,因此是处理期望的最佳方法。

The simple solution would seem to be just to catch any IOExceptions thrown by the code and give the user a "Inaccessible file" error message but is it possible to get a bit more fine-grained error messages. Is there a way to determine the difference between such errors as a file being locked by another program and the data being unreadable due to a hardware error?

简单的解决方案似乎只是捕获代码抛出的任何 IOExceptions 并为用户提供“无法访问的文件”错误消息,但是否有可能获得更细粒度的错误消息。有没有办法确定诸如文件被另一个程序锁定之类的错误与由于硬件错误导致数据无法读取之类的错误之间的区别?

Given the following C# code, how would you handle errors in a user friendly (as informative as possible) way?

鉴于以下 C# 代码,您将如何以用户友好(尽可能提供信息)的方式处理错误?

public class IO
{
   public List<string> ReadFile(string path)
   {
      FileInfo file = new FileInfo(path);

      if (!file.Exists)
      {
         throw new FileNotFoundException();
      }

      StreamReader reader = file.OpenText();
      List<string> text = new List<string>();

      while (!reader.EndOfStream)
      {
         text.Add(reader.ReadLine());
      }

      reader.Close();
      reader.Dispose();
      return text;
   }

   public void WriteFile(List<string> text, string path)
   {
      FileInfo file = new FileInfo(path);

      if (!file.Exists)
      {
         throw new FileNotFoundException();
      }

      StreamWriter writer = file.CreateText();

      foreach(string line in text)
      {
         writer.WriteLine(line);
      }

      writer.Flush();
      writer.Close();
      writer.Dispose();
   }
}

采纳答案by Dustman

...but is it possible to get a bit more fine-grained error messages.

...但是是否有可能获得更细粒度的错误消息。

Yes. Go ahead and catch IOException, and use the Exception.ToString()method to get a relatively relevant error message to display. Note that the exceptions generated by the .NET Framework will supply these useful strings, but if you are going to throw your own exception, you must remember to plug in that string into the Exception's constructor, like:

是的。继续 catch IOException,并使用该Exception.ToString()方法获取一个相对相关的错误信息来显示。请注意,.NET Framework 生成的异常将提供这些有用的字符串,但如果您要抛出自己的异常,则必须记住将该字符串插入Exception的构造函数中,例如:

throw new FileNotFoundException("File not found");

throw new FileNotFoundException("File not found");

Also, absolutely, as per Scott Dorman, use that usingstatement. The thing to notice, though, is that the usingstatement doesn't actually catchanything, which is the way it ought to be. Your test to see if the file exists, for instance, will introduce a race condition that may be rather vexing. It doesn't really do you any good to have it in there. So, now, for the reader we have:

此外,绝对,按照Scott Dorman 的using说法,请使用该语句。但是,要注意的是,该using语句实际上catch没有任何内容,这应该是它的方式。例如,您查看文件是否存在的测试将引入可能相当令人烦恼的竞争条件。把它放在那里真的对你没有任何好处。所以,现在,对于读者,我们有:

try {  
    using (StreamReader reader = file.OpenText()) {  
        // Your processing code here  
    }  
} catch (IOException e) {  
    UI.AlertUserSomehow(e.ToString());  
}

In short, for basic file operations:
1. Use using
2, Wrap the using statement or function in a try/catchthat catches IOException
3. Use Exception.ToString()in your catchto get a useful error message
4. Don't try to detect exceptional file issues yourself. Let .NET do the throwing for you.

总之,对于基本的文件操作:
1.使用using
2,收using语句或函数在try/catchcatchES IOException
3.使用Exception.ToString()在你catch得到一个有用的错误消息
4.不要尝试自行检测例外文件的问题。让 .NET 为您做投掷。

回答by Scott Dorman

The first thing you should change are your calls to StreamWriter and StreamReader to wrap them in a using statement, like this:

您应该更改的第一件事是调用 StreamWriter 和 StreamReader 以将它们包装在 using 语句中,如下所示:

using (StreamReader reader = file.OpenText())
{
   List<string> text = new List<string>();
   while (!reader.EndOfStream)
   {
      text.Add(reader.ReadLine());
   }
}

This will take care of calling Close and Dispose for you and will actually wrap it in a try/finally block so the actual compiled code looks like this:

这将负责为您调用 Close 和 Dispose 并将其实际包装在 try/finally 块中,因此实际编译的代码如下所示:

StreamReader reader = file.OpenText();
try
{
   List<string> text = new List<string>();
   while (!reader.EndOfStream)
   {
      text.Add(reader.ReadLine());
   }
}
finally
{
   if (reader != null)
      ((IDisposable)reader).Dispose();
}

The benefit here is that you ensure the stream gets closed even if an exception occurs.

这样做的好处是,即使发生异常,您也可以确保关闭流。

As far as any more explicit exception handling, it really depends on what you want to happen. In your example you explicitly test if the file exists and throw a FileNotFoundException which may be enough for your users but it may not.

至于任何更明确的异常处理,它实际上取决于您想要发生的事情。在您的示例中,您明确测试文件是否存在并抛出 FileNotFoundException 这对您的用户来说可能已经足够了,但可能还不够。

回答by Rune

  • Skip the File.Exists(); either handle it elsewhere or let CreateText()/OpenText() raise it.
  • The end-user usually only cares if it succeeds or not. If it fails, just say so, he don't want details.
  • 跳过 File.Exists(); 要么在别处处理它,要么让 CreateText()/OpenText() 提出它。
  • 最终用户通常只关心它是否成功。如果失败了,就直说吧,他不想要细节。

I haven't found a built-in way to get details about what and why something failed in .NET, but if you go native with CreateFile you have thousands of error-codes that can tell you what went wrong.

我还没有找到一种内置方法来获取有关 .NET 中失败的原因和原因的详细信息,但是如果您使用 CreateFile 本地化,您将有数千个错误代码可以告诉您出了什么问题。

回答by Brian

I would use the using statement to simplify closing the file. See MSDN the C# using statement

我会使用 using 语句来简化关闭文件的过程。参见MSDN C# using 语句

From MSDN:

来自 MSDN:

  using (TextWriter w = File.CreateText("log.txt")) {
     w.WriteLine("This is line one");
     w.WriteLine("This is line two");
  }
  using (TextReader r = File.OpenText("log.txt")) {
     string s;
     while ((s = r.ReadLine()) != null) {
        Console.WriteLine(s);
     }
  }

回答by Joe

I don't see the point in checking for existence of a file and throwing a FileNotFoundException with no message. The framework will throw the FileNotFoundException itself, with a message.

我不认为检查文件是否存在并抛出没有消息的 FileNotFoundException 的意义。该框架将抛出​​ FileNotFoundException 本身,并带有一条消息。

Another problem with your example is that you should be using the try/finally pattern or the using statement to ensure your disposable classes are properly disposed even when there is an exception.

您的示例的另一个问题是您应该使用 try/finally 模式或 using 语句来确保即使出现异常也能正确处理一次性类。

I would do this something like the following, catch any exception outside the method, and display the exception's message :

我会执行如下操作,捕获方法之外的任何异常,并显示异常消息:

public IList<string> ReadFile(string path)
{
    List<string> text = new List<string>();
    using(StreamReader reader = new StreamReader(path))
    {
      while (!reader.EndOfStream)      
      {         
         text.Add(reader.ReadLine());      
      }
    }
    return text;
}

回答by Georgi

Perhaps this is not what you are looking for, but reconsider the kind you are using exception handling. At first exception handling should not be treated to be "user-friendly", at least as long as you think of a programmer as user.

也许这不是您想要的,但请重新考虑您正在使用的异常处理类型。首先,异常处理不应被视为“用户友好”,至少只要您将程序员视为用户。

A sum-up for that may be the following article http://goit-postal.blogspot.com/2007/03/brief-introduction-to-exception.html.

对此的总结可能是以下文章http://goit-postal.blogspot.com/2007/03/brief-introduction-to-exception.html