How do I "fork" a Stream in .NET?
As discussed before, when a BinaryReader or BinaryWriter gets closed, its underlying Stream get closed as well (aargh). Consider this situation: a routine R
is passed a MemoryStream, say M
; I would like to write some stuff to M
and then pass it to another routine for more processing (not necessarily writing). For convenience, I'd like to wrap M
in a BinaryWriter to do my writing. After writing, I'm done with the BinaryWriter but not with M
开发者_StackOverflow中文版.
void R(MemoryStream M)
{
using (B = new BinaryWriter(M))
{
// write some stuff using B
}
S(M); // now pass M to another routine for further processing
}
But, I can't dispose of the BinaryStream without closing M
.
Q: Is there a way to do any of the following?
- extract the underlying byte[] from a MemoryStream,
- clone a Stream
- reopen a Stream after it's been closed
You should better get the underlying byte[] buffer using
byte[] buffer = ms.GetBuffer();
And then copy the byte data using the Array.Copy() method. You are free to create a new stream with it.
You can use things like the MiscUtil.IO.NonClosingStreamWrapper
in MiscUtil, which wraps a Stream
and simply ignores Close
/Dispose
requests. For just this purpose.
void R(MemoryStream M)
{
using (B = new BinaryWriter(new NonClosingStreamWrapper(M)))
{
// write some stuff using B
}
S(M); // now pass M to another routine for further processing
}
You can:
- Call M.ToArray() to get the stream as an array of bytes.
- Subclass BinaryWriter and override the Dispose method to prevent closing of the child stream
Thanks to several who suggested ToArray, I was led to right answer, which is `M.GetBuffer'. ToArray is not too bad, but it
- makes a copy
- gets only part of the buffer
GetBuffer just grabs a reference to the underlying byte[], which is what I'm after.
Just to add it in here, a very simple solution would be not to Dispose() the writer.
void R(MemoryStream M)
{
B = new BinaryWriter(M);
// write some stuff using B
B.Flush();
S(M); // now pass M to another routine for further processing
}
Now you only have to worry about keeping B in scope, which it will be during R().
This may not be the best solution here, but it is worth noting that the Readers and Writers don't need Disposing themselves.
A somewhat naive approach is to use
byte buf[] = MemoryStream.ToArray();
To copy the stream contents to a byte array. You can turn it back into a stream with
MemoryStream ms = new MemoryStream(buf);
Accoring to this M.Clone(); should work. But i may be wrong...
精彩评论