4

Using a StreamReader, if you dispose the underlying stream, I thought you shouldn't be able to read anymore.

That this is true suggests this question, where it's suggested that you don't have to dispose the StreamWriter (in their case) if the life of the underlying stream is handled elsewhere.

But that's not the case. What I did was the following:

I have a file called delme.txt containing the following

abc
def
ghi

The I run this:

    Stream s = File.OpenRead(@"C:\delme.txt");
    StreamReader sr = new StreamReader(s, Encoding.ASCII);

    Console.WriteLine(sr.ReadLine());

    s.Dispose();

    Console.WriteLine(sr.ReadLine());

And the result is:

abc
def

How is this possible?

Community
  • 1
  • 1
Petar Ivanov
  • 91,536
  • 11
  • 82
  • 95

3 Answers3

10

Your StreamReader already read the next line into its buffer.
It won't go back to the source Stream until it runs out of data in its buffer.

In fact, it would be impossible for it to throw an exception in that case, since there is no idempotent way to find out whether a Stream has been disposed. (There is no IsDisposed property)

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
5

To add to @SLaks answer, here will demonstrate (using a file with a couple thousand lines of text):

        Stream s = File.OpenRead(path);
        StreamReader sr = new StreamReader(s, Encoding.ASCII);

        Console.WriteLine(sr.ReadLine());

        s.Dispose();

        int i = 1;
        try
        {
            while (!sr.EndOfStream)
            {
                Console.WriteLine(sr.ReadLine());
                i++;
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }

        Console.WriteLine(i + " lines total");

        Console.ReadLine();

It will print out lots and lots of lines, like a couple hundred, then will throw an Exception. My output ended like this:

qrs
tuv
wxy
zab
cde
fgh
ijk
lmn
Cannot access a closed file.
204 lines total

In fact we see that there is a constructor for StreamReader that takes a parameter bufferSize as the fourth parameter:

StreamReader sr = new StreamReader(s, Encoding.ASCII, false, 10000);

Using 10000, it actually prints out a total of 1248 lines for me before crashing. Also, the smallest possible value you can use is 1, and for that case, it still pre-fetches 25 lines.

mellamokb
  • 56,094
  • 12
  • 110
  • 136
0

What you need to understand here is what dispose is trying to do.

http://msdn.microsoft.com/en-us/library/ms227563.aspx

It says the TextReader will be an unusable state if the TextReader is finished. Perhaps, since it hasn't read everything, it is not considered finished; therefore, you can continue to use it. That is my guess.

TIHan
  • 632
  • 4
  • 12