【问题标题】:how to use StreamWriter class properly?如何正确使用 StreamWriter 类?
【发布时间】:2012-07-13 02:42:12
【问题描述】:

我正在使用StreamWriter 类进行文件操作,这段代码中是否有我没有看到的问题?

比如我需要把它放到try catch finally 块中吗?

StreamWriter sr = new StreamWriter(streamFolder);
sr.Write(details);

File.SetAttributes(streamFolder, FileAttributes.Hidden);
sr.Close();

【问题讨论】:

    标签: c# streamwriter


    【解决方案1】:

    您的代码有什么问题?如果在关闭流之前发生异常,则流将保持打开状态,并且不会释放系统资源:

    StreamWriter sr = new StreamWriter(streamFolder);
    sr.Write(details);
    // some exception occurs here 
    File.SetAttributes(streamFolder, FileAttributes.Hidden);
    sr.Close();
    

    因此,您需要确定该流将被关闭。这可以通过try...finally 块来实现:

    StreamWriter sr = new StreamWriter(streamFolder);
    
    try 
    {
       sr.Write(details);
       // some exception occurs here 
       File.SetAttributes(streamFolder, FileAttributes.Hidden);
    }
    finally
    {
       sr.Close();
    }
    

    但是 StreamWriter 实现了IDisposable 接口,所以你可以让 C# 编译器自动为你做这件事,方法是将 writer 的使用情况包装到 using 块中:

    using(StreamWriter sr = new StreamWriter(streamFolder)) 
    {
       sr.Write(details);
       // some exception occurs here 
       File.SetAttributes(streamFolder, FileAttributes.Hidden);
    }
    

    这段代码将被编译为:

    StreamWriter sr = new StreamWriter(streamFolder);
    
    try 
    {
       sr.Write(details);
       // some exception occurs here 
       File.SetAttributes(streamFolder, FileAttributes.Hidden);
    }
    finally
    {
       if (sr != null)
          sr.Dispose();
    }
    

    手动实现的唯一区别是空检查和方法Dispose被调用而不是Close。但实际上当你调用Close()Dispose() 时会执行相同的代码:

    this.Dispose(true);
    GC.SuppressFinalize(this);
    

    您可以在Dispose method implementation 上阅读更多内容。

    【讨论】:

      【解决方案2】:

      您可能应该使用 using 语句:

      using (StreamWriter sr = new StreamWriter(streamFolder))
      {
          sr.Write(details);
          File.SetAttributes(streamFolder, FileAttributes.Hidden);
      }
      

      在 using 块结束时,StreamWriter.Dispose 将被调用,无论是出现异常还是代码运行成功。

      【讨论】:

      • 这里有性能影响吗?我的意思是比较 .close() 和 using ,因为两者都是垃圾收集器?
      • 不,这与将整个代码包装在 try ... finally 中并在 finally 块中调用 Dispose 大致相同。
      • 嗯,这意味着它可以在创建时抛出异常(文件访问冲突等)。所以无论如何你仍然需要try catch。 using 对某些东西很好,但对其他东西不是一概而论。
      【解决方案3】:

      你想使用:

        using (StreamWriter sr = new StreamWriter(streamFolder))
        {
            sr.Write(details); 
      
            File.SetAttributes(streamFolder, FileAttributes.Hidden); 
        }
      

      您不需要Close

      【讨论】:

      • 这里有性能影响吗?我的意思是比较 .close() 和 using ,因为两者都是垃圾收集器
      • @vettori 没有性能影响; using 语句是关于确保 StreamWriter 正确关闭,即使在 using 中抛出异常也是如此。
      • 通过使用“使用”,对象会在上下文之后自动释放
      【解决方案4】:

      将其包装在 using 块中

      using(StreamWriter sr = new StreamWriter(streamFolder))
      {
            sr.Write(details);
            File.SetAttributes(streamFolder, FileAttributes.Hidden);
      }
      

      确保您的命名正确,所以streamFolder 应该是fName。如果你觉得可以处理一些 IO(或其他)异常,你也可以把这段代码放到 try-catch-finally 中:

      StreamWriter sr;
      try
      {
          sr = new StreamWriter(streamFolder);
          sr.Write(details);
          File.SetAttributes(streamFolder, FileAttributes.Hidden);
      }
      catch(IOException ex)
      {
          //handling IO
      }
      finally
      {
          if (sr != null)
              sr.Dispose();
      }
      

      【讨论】:

      • 第二种方法会增加代码行数,我正在寻找优化的代码
      • @vettori 你应该知道using 被编译器翻译成try-finally。所以你仍然得到这个代码。我会谨慎进行任何微优化。
      • @oleksii,是吗?在统一时,至少不会捕获文件异常。
      【解决方案5】:

      System.IO.StreamWriter 是一个 System.IDisposable

      你必须处理它。你为什么要关闭你不打开的东西?

      【讨论】:

      • 是的,它会打开它,所以它必须关闭它。不要关闭你没有打开的东西,这是一个坏习惯。
      • 什么是“它”?您的意思是 StreamWriter 必须自行关闭吗?
      • 我确定它在处理过程中调用了“关闭”方法。是的,如果一个对象能够自动打开,它就能够自动关闭。
      • 我知道这有点老了,但 StreamWriter 不会自行关闭,除非您将其包装在 using 语句中,或者在其上调用 StreamWriter.Close。我不确定 user1485585 所指的“自动关闭”是什么。
      猜你喜欢
      • 1970-01-01
      • 2014-03-03
      • 1970-01-01
      • 2018-10-17
      • 2015-03-10
      • 1970-01-01
      • 1970-01-01
      • 2012-02-09
      • 2018-09-03
      相关资源
      最近更新 更多