Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using StreamReader after the underlying stream has beed disposed?

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?

like image 860
Petar Ivanov Avatar asked Dec 07 '22 19:12

Petar Ivanov


2 Answers

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)

like image 58
SLaks Avatar answered Jan 10 '23 18:01

SLaks


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.

like image 24
mellamokb Avatar answered Jan 10 '23 18:01

mellamokb