none
FileStream,StreamReader のクローズ処理 RRS feed

  • 質問

  • いつもお世話になっております。
    環境:VS2005 C# WinXP

     

    サンプルの元ネタ
    http://www.atmarkit.co.jp/fdotnet/csharptips/005file/005file.html

    FileStream   fs = new FileStream(arg, FileMode.Open);
    StreamReader sr = new StreamReader(fs, Encoding.GetEncoding(932));
    sr.Close();
    fs.Close();

     

    上の例ではファイルの読み込みに
    FileStreamと、StreamReader を併用しており、
    その両方に対してクローズ処理を行っています。
    クローズ処理は両方に対して必要なのでしょうか。
    どちらか一方だけでよいのではという疑いを持っています。
    宜しくお願い致します。

     

    2009年1月2日 8:26

回答

  •  Myon さんからの引用

    クローズ処理は両方に対して必要なのでしょうか。
    どちらか一方だけでよいのではという疑いを持っています。

     

    MSDNのStreamReader.Close メソッドの説明には「その基になるストリームを閉じ」と記載されています。そのままの意味で解釈するのであれば、StreamReader側のみcloseすればよいと解釈できます。

    デバッグ実行中に、openfilesコマンドなどを利用すれば状態が確認できると思いますよ。

    2009年1月2日 15:27
  • 謹賀新年!(^^)!ふ~です。

     

    普通は、両方クローズしますが。。。

    かなり面白い発見ですね。確かに、片方だけで上手く動作します。

    しかし、ソースコードレビューでは、説明が大変と思います。

     

    <実験用ソース>

    Code Snippet

    using System;
    using System.Text;
    using System.IO;
    using System.Windows.Forms;

    namespace CatCmmand
    {
     public partial class Form1 : Form
     {
      public Form1()
      {
       InitializeComponent();
      }

      private void button1_Click(object sender, EventArgs e)
      {

       string line;
       for (int iLoop = 0; iLoop < 2; iLoop++)
       {
        FileStream fs = new FileStream(@"C:\work\Test1.txt", FileMode.OpenOrCreate);
        StreamReader sr = new StreamReader(fs, Encoding.GetEncoding(932));

        while ((line = sr.ReadLine()) != null)
        {
         Console.WriteLine(line);
        }

        sr.Close();

        //fs.Close();

        if (!fs.CanRead)
        {
         Console.WriteLine("System.ObjectDisposedException' の例外をスローしました");
        }

       }
      }

     }
    }

     

     

    fsとsrをデバッガーのウォッチポイントで眺めますと、sr.Close()で、fs.CanReadがfalseに変化するのが分かります。

    sr.Close()だけで、再度、fsがオープン出来ますので、完全にfsもクローズしています。

    また、sr.Close()しますと、fsでは、System.ObjectDisposedExceptionが発生しています。

    2009年1月5日 4:15
  • 本題からはずれますが、実際にコードを書くならCloseを呼ばずにusingに任せた方が良いと思います。

    処理中に例外が起きた時にもCloseを呼ばないと困ってしまうのでusingを使って{}を抜けた時に自動的に呼ぶようにします。

    Code Snippet

    using(FileStream   fs = new FileStream(arg, FileMode.Open))
    using(StreamReader sr = new StreamReader(fs, Encoding.GetEncoding(932)))

    {

      //処理

    }

     

    2009年1月5日 8:05

すべての返信

  •  Myon さんからの引用

    クローズ処理は両方に対して必要なのでしょうか。
    どちらか一方だけでよいのではという疑いを持っています。

     

    MSDNのStreamReader.Close メソッドの説明には「その基になるストリームを閉じ」と記載されています。そのままの意味で解釈するのであれば、StreamReader側のみcloseすればよいと解釈できます。

    デバッグ実行中に、openfilesコマンドなどを利用すれば状態が確認できると思いますよ。

    2009年1月2日 15:27
  • GENZO様

    お答えいただきありがとうございました。

    openfilesコマンドを試してみたいと思います。

     

     

    2009年1月3日 17:58
  • 謹賀新年!(^^)!ふ~です。

     

    普通は、両方クローズしますが。。。

    かなり面白い発見ですね。確かに、片方だけで上手く動作します。

    しかし、ソースコードレビューでは、説明が大変と思います。

     

    <実験用ソース>

    Code Snippet

    using System;
    using System.Text;
    using System.IO;
    using System.Windows.Forms;

    namespace CatCmmand
    {
     public partial class Form1 : Form
     {
      public Form1()
      {
       InitializeComponent();
      }

      private void button1_Click(object sender, EventArgs e)
      {

       string line;
       for (int iLoop = 0; iLoop < 2; iLoop++)
       {
        FileStream fs = new FileStream(@"C:\work\Test1.txt", FileMode.OpenOrCreate);
        StreamReader sr = new StreamReader(fs, Encoding.GetEncoding(932));

        while ((line = sr.ReadLine()) != null)
        {
         Console.WriteLine(line);
        }

        sr.Close();

        //fs.Close();

        if (!fs.CanRead)
        {
         Console.WriteLine("System.ObjectDisposedException' の例外をスローしました");
        }

       }
      }

     }
    }

     

     

    fsとsrをデバッガーのウォッチポイントで眺めますと、sr.Close()で、fs.CanReadがfalseに変化するのが分かります。

    sr.Close()だけで、再度、fsがオープン出来ますので、完全にfsもクローズしています。

    また、sr.Close()しますと、fsでは、System.ObjectDisposedExceptionが発生しています。

    2009年1月5日 4:15
  • 本題からはずれますが、実際にコードを書くならCloseを呼ばずにusingに任せた方が良いと思います。

    処理中に例外が起きた時にもCloseを呼ばないと困ってしまうのでusingを使って{}を抜けた時に自動的に呼ぶようにします。

    Code Snippet

    using(FileStream   fs = new FileStream(arg, FileMode.Open))
    using(StreamReader sr = new StreamReader(fs, Encoding.GetEncoding(932)))

    {

      //処理

    }

     

    2009年1月5日 8:05
  • こんにちは。中川俊輔 です。

     

    皆様、回答ありがとうございます。

     

    Myon さん、フォーラムのご利用ありがとうございます。

    勝手ながら、有用な情報と思われる回答へ回答済みチェックをつけさせていただきました。

     

    今後ともフォーラムをよろしくお願いします。

    それでは!

    2009年1月14日 9:30