正确处理文件流和二进制流以及处理文件流

时间:2012-01-01 08:25:40

标签: c# error-handling program-flow

实际上,我尝试了对代码进行防错,最终使其看起来非常混乱。

我有一个功能设置来读取某种类型的文件。我希望函数在出现问题时返回false,如果一切正常则返回true。我无法弄清楚如何构建一切。

我有一个尝试打开文件流的初始try-catch块。在那之后,我在读取过程中进行了一些其他检查,例如文件大小和某些偏移处的值。我设置的方式是使用if else语句。如:

if(condition){

}
else{
    MessageBox.Show("There was an error");
    br.Dispose();
    fs.Dispose();
    return false;
}

... br是二进制阅读器,fs是文件流。像这样有很多块,这么多次写同样的东西似乎是不好的做法。首先想到的是将整个事物包装在try-catch语句中并抛出异常而不是使用if else块。我记得在阅读try-catch语句时,拥有它们很好,但不能用它们包装所有内容。说实话,我仍然不完全理解为什么将所有内容包装在try catch语句中是不好的做法,因为它们只有在出现错误时才会生效,在这种情况下程序会向南移动无论如何...

另外,我是否必须关闭二进制阅读器和文件流,还是关闭另一个?有没有办法在不必处理它们的情况下使用它们?

5 个答案:

答案 0 :(得分:5)

如何使用using关键字?这包括你在try - finally块中使用IDisposable;

bool success = true;

using(var fs = new FileStream(fileName, FileMode.Create)))
using(var br = new BinaryReader(fs))
{
  // do something
  success = result;
}

return success;

嵌套使用块将确保始终正确关闭和处理文件流和二进制阅读器。

您可以阅读more about using in MSDN。它使得IDisposable的使用更加简洁,无需明确的激活处理。

关于你的陈述:

  

我记得在阅读关于try-catch语句的时候,这很好   拥有它们,但不要用它们包装所有东西。

我总是使用简单的规则,如果我无法处理并从特定代码块中的异常中恢复,请不要尝试捕获它。允许异常将堆栈'冒泡'到一个更有意义的方法来捕获它。使用这种方法,您会发现您不需要添加许多try-catch块,您将倾向于在与服务集成时使用它们(例如文件系统,网络等...),但您的业务逻辑几乎总是如此没有异常处理机制。

答案 1 :(得分:1)

只需将using关键字用于您的一次性对象即可。在using关键字的区块内,您可以throw例外或return,而无需担心处置;它将自动发生在您身上。

try-catch块不是一个好主意,只是因为存在一个更好的选择:try-finally块。但是using关键字更好,因为它基本上扩展为try-finally块,它负责处理对象。

关闭文件流也将关闭二进制阅读器,因此将处理它们。为什么要在不处理它们的情况下使用它们?处置它们会更好,通过using处理它们是最好的办法。

答案 2 :(得分:0)

我认为确保文件流处理的最佳方法是使用以下using块来包装它们

using (FileStream)
{
    ....
}

答案 3 :(得分:0)

是的,这是不好的做法。

您应该抛出异常,而不是返回指示问题是否发生的布尔值。例如:

if (headNotValid)
   throw new Exception("Header was not valid");

在某些情况下,最好建立一个新的异常类。

使用继承自IDisposable的类时,应使用using指令。

using (var stream = new FileStream(filename))
{
}

即使在using块中抛出异常,也可以保证您的流被处理掉。

总之,我更喜欢这样的事情:

private void string ParseFile(string filename)
{
     using (var stream = new FileStream(filename))
     {
           if (somethingNotValid)
              throw new Exception(...);

           return ...;
     }
}

在你的主要:

{
     try
     {
          var value = ParseFile(filename);
     }
     catch (Exception)
     {
          Console.WriteLine(..);
     }
}

答案 4 :(得分:0)

使用using关键字。使用using,您可以重写这样的内容:

public static int CountCars()
{
    SqlConnection conn = new SqlConnection(connectionString);
    try
    {
      SqlCommand cmd = conn.CreateCommand();
      conn.Open();
      try
      {
        cmd.CommandText = "SELECT COUNT(1) FROM Carsd";

        return (int)cmd.ExecuteScalar();
      }
      finally
      {
        if(cmd != null)
          cmd.Dispose();
      }
    }
    finally
    {
      if(cmd != null)
        conn.Dispose();
    }
}

进入这个:

public static int CountCars()
{
    using(SqlConnection conn = new SqlConnection(connectionString))
    using(SqlCommand cmd = conn.CreateCommand())
    {
        conn.Open();
        cmd.CommandText = "SELECT COUNT(1) FROM Carsd";

        return (int)cmd.ExecuteScalar();
    }

}

两个代码片段在编译时将生成完全相同的IL代码。这些示例来自http://coding.abel.nu/2011/12/idisposable-and-using-in-c/,其中我写了一些有关使用和IDisposable的详细信息。