Home All Groups Group Topic Archive Search About

BinaryReader (et al) leave open

Author
3 Oct 2005 5:39 PM
William Stacey [MVP]
Shouldn't BinaryReader and BinaryWriter (or any stream that takes another
stream) have an overload to LeaveInnerStream open.

bool leaveInnerStreamOpen = true;
using(BinaryReader br = new BinaryReader(innerStream, leaveInnerStreamOpen))
{
     // Use the br stream, but don't close innerStream after Dispose.
}

That way you can pass stream around to helper methods that may wrap the
stream in another stream and not close the first stream after the helper is
done.

--
William Stacey [MVP]

Author
3 Oct 2005 6:53 PM
Jon Skeet [C# MVP]
William Stacey [MVP] <stac***@mvps.org> wrote:
> Shouldn't BinaryReader and BinaryWriter (or any stream that takes another
> stream) have an overload to LeaveInnerStream open.

Yes, they should. I've got a NonClosingStreamWrapper class for
precisely this reason.

See http://www.pobox.com/~skeet/csharp/miscutil

It would be much nicer not to have to do the wrapping in the first
place :)

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Author
3 Oct 2005 7:03 PM
William Stacey [MVP]
Thanks Jon.  I would think they could add this before 2.0 gets out the door.
One more constructor overload and a property and Dispose has to change.  Not
sure what that would break (If anything) however.

--
William Stacey [MVP]

Show quote
"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MPG.1dab8e7bcc36886398c847@msnews.microsoft.com...
> William Stacey [MVP] <stac***@mvps.org> wrote:
>> Shouldn't BinaryReader and BinaryWriter (or any stream that takes another
>> stream) have an overload to LeaveInnerStream open.
>
> Yes, they should. I've got a NonClosingStreamWrapper class for
> precisely this reason.
>
> See http://www.pobox.com/~skeet/csharp/miscutil
>
> It would be much nicer not to have to do the wrapping in the first
> place :)
>
> --
> Jon Skeet - <sk***@pobox.com>
> http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
> If replying to the group, please do not mail me too
Author
4 Oct 2005 3:01 AM
Daniel O'Connell [C# MVP]
"William Stacey [MVP]" <stac***@mvps.org> wrote in message
news:Oy9Fd0EyFHA.1032@TK2MSFTNGP12.phx.gbl...
> Thanks Jon.  I would think they could add this before 2.0 gets out the
> door. One more constructor overload and a property and Dispose has to
> change.  Not sure what that would break (If anything) however.
>

It would make things a bit more difficult, one type has two different sets
of dispose semantics, so definitivly closing a file is a little harder.
Author
4 Oct 2005 3:27 AM
William Stacey [MVP]
Not sure I understand Daniel.  A FileStream for example, does not take a
stream in the constructor, so I don't have worry about closing an
innerstream there.  So that will not change.  It is only when I "wrap" a FS
(for example) in something like a TextWriter or BinaryWriter.  In many
cases, I don't want dispose on those streams to close the innerstream as I
want control over that and close it when done.  TMK, this does not change
dispose semantics from the Users perspective as dispose still gets called as
normal.

--
William Stacey [MVP]

Show quote
"Daniel O'Connell [C# MVP]" <onyxkirx@--NOSPAM--comcast.net> wrote in
message news:OsPDi$IyFHA.448@TK2MSFTNGP11.phx.gbl...
>
> "William Stacey [MVP]" <stac***@mvps.org> wrote in message
> news:Oy9Fd0EyFHA.1032@TK2MSFTNGP12.phx.gbl...
>> Thanks Jon.  I would think they could add this before 2.0 gets out the
>> door. One more constructor overload and a property and Dispose has to
>> change.  Not sure what that would break (If anything) however.
>>
>
> It would make things a bit more difficult, one type has two different sets
> of dispose semantics, so definitivly closing a file is a little harder.
>
Author
4 Oct 2005 6:24 AM
Jon Skeet [C# MVP]
William Stacey [MVP] <stac***@mvps.org> wrote:
> Thanks Jon.  I would think they could add this before 2.0 gets out the door.

I don't think so, to be honest.

> One more constructor overload and a property and Dispose has to change.  Not
> sure what that would break (If anything) however.

Indeed - there'd be a fair amount of testing needed.

Maybe for 3.0...

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Author
4 Oct 2005 2:52 AM
Lloyd Dupont
> Shouldn't BinaryReader and BinaryWriter (or any stream that takes another
> stream) have an overload to LeaveInnerStream open.
>
> bool leaveInnerStreamOpen = true;
> using(BinaryReader br = new BinaryReader(innerStream,
> leaveInnerStreamOpen))
> {
>     // Use the br stream, but don't close innerStream after Dispose.
> }

try this:
BinaryReader br = new BinaryReader(innerStream, leaveInnerStreamOpen);
// Use the br stream, but don't close innerStream after Dispose.

the reason you would call Dispose() is if you want to release the inner
resource, namely the stream.
don't use using, the reader would still be collected but you won't have your
stream closed!!


Show quote
>
> That way you can pass stream around to helper methods that may wrap the
> stream in another stream and not close the first stream after the helper
> is done.
>
> --
> William Stacey [MVP]
>
>
>
Author
4 Oct 2005 3:19 AM
William Stacey [MVP]
The issue is BinaryReader does not currently have the "leaveInnerStreamOpen"
overload.  So you can't code it that way.  If you could, I would still use
the Using clause to close the reader.  It would just not close the
innerstream itself.

--
William Stacey [MVP]

Show quote
"Lloyd Dupont" <net.galador@ld> wrote in message
news:uzNG76IyFHA.1256@TK2MSFTNGP09.phx.gbl...
>> Shouldn't BinaryReader and BinaryWriter (or any stream that takes another
>> stream) have an overload to LeaveInnerStream open.
>>
>> bool leaveInnerStreamOpen = true;
>> using(BinaryReader br = new BinaryReader(innerStream,
>> leaveInnerStreamOpen))
>> {
>>     // Use the br stream, but don't close innerStream after Dispose.
>> }
>
> try this:
> BinaryReader br = new BinaryReader(innerStream, leaveInnerStreamOpen);
> // Use the br stream, but don't close innerStream after Dispose.
>
> the reason you would call Dispose() is if you want to release the inner
> resource, namely the stream.
> don't use using, the reader would still be collected but you won't have
> your stream closed!!
>
>
>>
>> That way you can pass stream around to helper methods that may wrap the
>> stream in another stream and not close the first stream after the helper
>> is done.
>>
>> --
>> William Stacey [MVP]
>>
>>
>>
>
>
Author
4 Oct 2005 3:38 AM
Lloyd Dupont
> The issue is BinaryReader does not currently have the
> "leaveInnerStreamOpen" overload.  So you can't code it that way.  If you
> could, I would still use the Using clause to close the reader.  It would
> just not close the innerstream itself.
>
Ask your self: what means closing the BinaryReader?

A binary reader is nothing if itself if it doesn't have a Stream.
Close it means nothing if not closing the underlying stream.
I don't think they would ever had this constructor because: what's the point
of disposing it if not disposing of the iner stream?

I repeaat: Do't use using
Author
4 Oct 2005 4:17 AM
William Stacey [MVP]
> Ask your self: what means closing the BinaryReader?
>
> A binary reader is nothing if itself if it doesn't have a Stream.
> Close it means nothing if not closing the underlying stream.
> I don't think they would ever had this constructor because: what's the
> point of disposing it if not disposing of the iner stream?

BinaryReader is just a simple example.  That said, the Dispose method in
BinaryReader does more then just close the innerstream.  It also closes its
internal state fields.  You could imagine other more complex streams that
*need to close down more stuff to close clean - regardless if it closes
innerstream or not.  Check the SslStream class for examples of this.

> I don't think they would ever had this constructor because: what's the
> point of disposing it if not disposing of the inner stream?

There may be other state you need to close as BinaryReader also sets a bunch
of flags.  Look at the code.

>I repeat: Do't use using

I disagree.  What is your argument.

--
William Stacey [MVP]
Author
4 Oct 2005 4:51 AM
Lloyd Dupont
> I disagree.  What is your argument.
I disagree with you, what is the use of Dipose() anyway?

Anyway as you are impervious to the voice of reson, I copy the code from BinaryReader.Dispose() below (coming straight out of reflector) and I would be keen to know why "it is important" to call Dispose() on it.
protected virtual void Dispose(bool disposing)
{
      if (disposing)
      {
            Stream stream1 = this.m_stream;
            this.m_stream = null;
            if (stream1 != null)
            {
                  stream1.Close();
            }
      }
      this.m_stream = null;
      this.m_buffer = null;
      this.m_decoder = null;
      this.m_charBytes = null;
      this.m_singleChar = null;
      this.m_charBuffer = null;
}
Author
4 Oct 2005 5:19 AM
William Stacey [MVP]
For the same reason you want to dispose of any object.  You want its internal state to reflect it is disposed/closed.  You don't want any future code that has a ref to the object to be able to call methods on the disposed stream (i.e. Read()).  So I want to dispose of your wrapper stream, but you may not want to dispose of the innerstream - however you may want to Flush() it in the Dispose method like:
protected override void Dispose(bool disposing)
{
      try
      {
            if (!disposing)
            {
                  return;
            }
            if (this.leaveStreamOpen)
            {
                  this.innerStream.Flush();
            }
            else
            {
                  this.innerStream.Close();
            }
      }
      finally
      {
            base.Dispose(disposing);
      }
}-- William Stacey [MVP] "Lloyd Dupont" <net.galador@ld> wrote in message news:e6c2W9JyFHA.1856@TK2MSFTNGP12.phx.gbl...
  > I disagree.  What is your argument.
  I disagree with you, what is the use of Dipose() anyway?

  Anyway as you are impervious to the voice of reson, I copy the code from BinaryReader.Dispose() below (coming straight out of reflector) and I would be keen to know why "it is important" to call Dispose() on it.
protected virtual void Dispose(bool disposing)
{
      if (disposing)
      {
            Stream stream1 = this.m_stream;
            this.m_stream = null;
            if (stream1 != null)
            {
                  stream1.Close();
            }
      }
      this.m_stream = null;
      this.m_buffer = null;
      this.m_decoder = null;
      this.m_charBytes = null;
      this.m_singleChar = null;
      this.m_charBuffer = null;
}
Author
4 Oct 2005 5:54 AM
Lloyd Dupont
oh yeah, Flush(), my bad :-(
so what of

BinaryReader br = new BinraryReader(stream)
// do stuff
stream.Flush()

here you go, achieve the desired result.
doesn't it?
  "William Stacey [MVP]" <stac***@mvps.org> wrote in message news:eywO7MKyFHA.3856@tk2msftngp13.phx.gbl...
  For the same reason you want to dispose of any object.  You want its internal state to reflect it is disposed/closed.  You don't want any future code that has a ref to the object to be able to call methods on the disposed stream (i.e. Read()).  So I want to dispose of your wrapper stream, but you may not want to dispose of the innerstream - however you may want to Flush() it in the Dispose method like:
protected override void Dispose(bool disposing)
{
      try
      {
            if (!disposing)
            {
                  return;
            }
            if (this.leaveStreamOpen)
            {
                  this.innerStream.Flush();
            }
            else
            {
                  this.innerStream.Close();
            }
      }
      finally
      {
            base.Dispose(disposing);
      }
}-- William Stacey [MVP] "Lloyd Dupont" <net.galador@ld> wrote in message news:e6c2W9JyFHA.1856@TK2MSFTNGP12.phx.gbl...
    > I disagree.  What is your argument.
    I disagree with you, what is the use of Dipose() anyway?

    Anyway as you are impervious to the voice of reson, I copy the code from BinaryReader.Dispose() below (coming straight out of reflector) and I would be keen to know why "it is important" to call Dispose() on it.
protected virtual void Dispose(bool disposing)
{
      if (disposing)
      {
            Stream stream1 = this.m_stream;
            this.m_stream = null;
            if (stream1 != null)
            {
                  stream1.Close();
            }
      }
      this.m_stream = null;
      this.m_buffer = null;
      this.m_decoder = null;
      this.m_charBytes = null;
      this.m_singleChar = null;
      this.m_charBuffer = null;
}
Author
4 Oct 2005 6:57 AM
William Stacey [MVP]
No.  Because when br goes out of scope and gets disposed it closes my stream.  I don't want the stream disposed, hence the reason to topic started.  What is needed is the leaveInnerStream switch.  Remember innerstream could be a NetworkStream and I may have helper method that wrap that stream in a typical server program to operate on the NetworkStream.  When these methods return they would close the NetworkStream unexpectedly.

--
William Stacey [MVP]

  "Lloyd Dupont" <net.galador@ld> wrote in message news:ODifYgKyFHA.3720@TK2MSFTNGP14.phx.gbl...
  oh yeah, Flush(), my bad :-(
  so what of

  BinaryReader br = new BinraryReader(stream)
  // do stuff
  stream.Flush()

  here you go, achieve the desired result.
  doesn't it?
    "William Stacey [MVP]" <stac***@mvps.org> wrote in message news:eywO7MKyFHA.3856@tk2msftngp13.phx.gbl...
    For the same reason you want to dispose of any object.  You want its internal state to reflect it is disposed/closed.  You don't want any future code that has a ref to the object to be able to call methods on the disposed stream (i.e. Read()).  So I want to dispose of your wrapper stream, but you may not want to dispose of the innerstream - however you may want to Flush() it in the Dispose method like:
protected override void Dispose(bool disposing)
{
      try
      {
            if (!disposing)
            {
                  return;
            }
            if (this.leaveStreamOpen)
            {
                  this.innerStream.Flush();
            }
            else
            {
                  this.innerStream.Close();
            }
      }
      finally
      {
            base.Dispose(disposing);
      }
}-- William Stacey [MVP] "Lloyd Dupont" <net.galador@ld> wrote in message news:e6c2W9JyFHA.1856@TK2MSFTNGP12.phx.gbl...
      > I disagree.  What is your argument.
      I disagree with you, what is the use of Dipose() anyway?

      Anyway as you are impervious to the voice of reson, I copy the code from BinaryReader.Dispose() below (coming straight out of reflector) and I would be keen to know why "it is important" to call Dispose() on it.
protected virtual void Dispose(bool disposing)
{
      if (disposing)
      {
            Stream stream1 = this.m_stream;
            this.m_stream = null;
            if (stream1 != null)
            {
                  stream1.Close();
            }
      }
      this.m_stream = null;
      this.m_buffer = null;
      this.m_decoder = null;
      this.m_charBytes = null;
      this.m_singleChar = null;
      this.m_charBuffer = null;
}
Author
4 Oct 2005 7:21 AM
Lloyd Dupont
I refer you to the source code again
protected virtual void Dispose(bool disposing)
{
      if (disposing)
      {
            Stream stream1 = this.m_stream;
            this.m_stream = null;
            if (stream1 != null)
            {
                  stream1.Close();
            }
      }
      this.m_stream = null;
      this.m_buffer = null;
      this.m_decoder = null;
      this.m_charBytes = null;
      this.m_singleChar = null;
      this.m_charBuffer = null;
}the stream is close only if 'disposing' that means only if the reader has been disposed explicitely (as opposed to simply collected)"William Stacey [MVP]" <stac***@mvps.org> wrote in message news:%23lALdDLyFHA.736@tk2msftngp13.phx.gbl...
  No.  Because when br goes out of scope and gets disposed it closes my stream.  I don't want the stream disposed, hence the reason to topic started.  What is needed is the leaveInnerStream switch.  Remember innerstream could be a NetworkStream and I may have helper method that wrap that stream in a typical server program to operate on the NetworkStream.  When these methods return they would close the NetworkStream unexpectedly.

  --
  William Stacey [MVP]

    "Lloyd Dupont" <net.galador@ld> wrote in message news:ODifYgKyFHA.3720@TK2MSFTNGP14.phx.gbl...
    oh yeah, Flush(), my bad :-(
    so what of

    BinaryReader br = new BinraryReader(stream)
    // do stuff
    stream.Flush()

    here you go, achieve the desired result.
    doesn't it?
      "William Stacey [MVP]" <stac***@mvps.org> wrote in message news:eywO7MKyFHA.3856@tk2msftngp13.phx.gbl...
      For the same reason you want to dispose of any object.  You want its internal state to reflect it is disposed/closed.  You don't want any future code that has a ref to the object to be able to call methods on the disposed stream (i.e. Read()).  So I want to dispose of your wrapper stream, but you may not want to dispose of the innerstream - however you may want to Flush() it in the Dispose method like:
protected override void Dispose(bool disposing)
{
      try
      {
            if (!disposing)
            {
                  return;
            }
            if (this.leaveStreamOpen)
            {
                  this.innerStream.Flush();
            }
            else
            {
                  this.innerStream.Close();
            }
      }
      finally
      {
            base.Dispose(disposing);
      }
}-- William Stacey [MVP] "Lloyd Dupont" <net.galador@ld> wrote in message news:e6c2W9JyFHA.1856@TK2MSFTNGP12.phx.gbl...
        > I disagree.  What is your argument.
        I disagree with you, what is the use of Dipose() anyway?

        Anyway as you are impervious to the voice of reson, I copy the code from BinaryReader.Dispose() below (coming straight out of reflector) and I would be keen to know why "it is important" to call Dispose() on it.
protected virtual void Dispose(bool disposing)
{
      if (disposing)
      {
            Stream stream1 = this.m_stream;
            this.m_stream = null;
            if (stream1 != null)
            {
                  stream1.Close();
            }
      }
      this.m_stream = null;
      this.m_buffer = null;
      this.m_decoder = null;
      this.m_charBytes = null;
      this.m_singleChar = null;
      this.m_charBuffer = null;
}
Author
4 Oct 2005 5:48 PM
Jon Skeet [C# MVP]
William Stacey [MVP] <stac***@mvps.org> wrote:
> No.  Because when br goes out of scope and gets disposed it closes my stream.

It only gets disposed if you have a using statement, however. I don't
believe BinaryReader has a finalizer, so that wouldn't dispose of it
either.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Author
4 Oct 2005 10:03 AM
Damien
William Stacey [MVP] wrote:
Show quote
> Shouldn't BinaryReader and BinaryWriter (or any stream that takes another
> stream) have an overload to LeaveInnerStream open.
>
> bool leaveInnerStreamOpen = true;
> using(BinaryReader br = new BinaryReader(innerStream, leaveInnerStreamOpen))
> {
>      // Use the br stream, but don't close innerStream after Dispose.
> }
>
> That way you can pass stream around to helper methods that may wrap the
> stream in another stream and not close the first stream after the helper is
> done.
>
> --
> William Stacey [MVP]

Hi,

Wouldn't this impose on these wrapper-streams additional constraints -
such as the current seek position of the underlying stream? AFAIK,
there are currently no such guarantees - precisely before it closes the
stream when you finish with it, and it assumes once you pass it a
stream that it is in complete control.

That said, I believe all current implementations do leave the
underlying stream at the "expected" position at all times. So you could
probably interleave two readers on the same underlying stream (at least
until you Dispose one...)

Damien

Damien

AddThis Social Bookmark Button