working around 'using wrapped MemoryStream immutability ?
-
I can't do this because the MemoryStream is immutable: (code excerpt)
using(MemoryStream mstream = new MemoryStream(File.ReadAllBytes(filepath)))
{
if (useDecryption)
{
mstream = decryptor(mstream);
mstream.Position = 0;
}if (useDecompression) { mstream = decompressor(mstream); mstream.Position = 0; } result = (T) dcs.ReadObject(mstream)
}
So, okay, I can do this: (code excerpt)
MemoryStream mstream = new MemoryStream(File.ReadAllBytes(filepath));
if (useDecryption)
{
mstream = decryptor(mstream);
mstream.Position = 0;
}if (useDecompression)
{
mstream = decompressor(mstream);
mstream.Position = 0;
}result = (T) dcs.ReadObject(mstream);
But that violates my early .NET memory-potty-training. Best/better practice ? Perhaps better to pass a byte array ? thanks, Bill
«While I complain of being able to see only a shadow of the past, I may be insensitive to reality as it is now, since I'm not at a stage of development where I'm capable of seeing it. A few hundred years later another traveler despairing as myself, may mourn the disappearance of what I may have seen, but failed to see.» Claude Levi-Strauss (Tristes Tropiques, 1955)
-
I can't do this because the MemoryStream is immutable: (code excerpt)
using(MemoryStream mstream = new MemoryStream(File.ReadAllBytes(filepath)))
{
if (useDecryption)
{
mstream = decryptor(mstream);
mstream.Position = 0;
}if (useDecompression) { mstream = decompressor(mstream); mstream.Position = 0; } result = (T) dcs.ReadObject(mstream)
}
So, okay, I can do this: (code excerpt)
MemoryStream mstream = new MemoryStream(File.ReadAllBytes(filepath));
if (useDecryption)
{
mstream = decryptor(mstream);
mstream.Position = 0;
}if (useDecompression)
{
mstream = decompressor(mstream);
mstream.Position = 0;
}result = (T) dcs.ReadObject(mstream);
But that violates my early .NET memory-potty-training. Best/better practice ? Perhaps better to pass a byte array ? thanks, Bill
«While I complain of being able to see only a shadow of the past, I may be insensitive to reality as it is now, since I'm not at a stage of development where I'm capable of seeing it. A few hundred years later another traveler despairing as myself, may mourn the disappearance of what I may have seen, but failed to see.» Claude Levi-Strauss (Tristes Tropiques, 1955)
Disposing a
MemoryStream
doesn't release any unmanaged resources. It simply sets some flags to indicate that future attempts to read or write the stream should throw an exception.protected override void Dispose(bool disposing)
{
try {
if (disposing) {
_isOpen = false;
_writable = false;
_expandable = false;
// Don't set buffer to null - allow TryGetBuffer, GetBuffer & ToArray to work.
#if FEATURE_ASYNC_IO
_lastReadTask = null;
#endif
}
}
finally {
// Call base.Close() to cleanup async IO resources
base.Dispose(disposing);
}
}Reference Source[^] Despite the comment about the base method cleaning up async IO resources, it doesn't:
protected virtual void Dispose(bool disposing)
{
// Note: Never change this to call other virtual methods on Stream
// like Write, since the state on subclasses has already been
// torn down. This is the last code to run on cleanup for a stream.
}Reference Source[^] But I know what you mean - it doesn't feel right to omit the
using
statement. :) Perhaps a helper method to create the stream might help to hide the unpleasantness?private static MemoryStream CreateStream(byte[] rawBytes, IEnumerable<Func<MemoryStream, MemoryStream>> decorators)
{
var result = new MemoryStream(rawBytes);foreach (Func<MemoryStream, MemoryStream> decorator in decorators) { result = decorator(result); result.Position = 0; } return result;
}
...
var decorators = new List<Func<MemoryStream, MemoryStream>>();
if (useDecryption) decorators.Add(decryptor);
if (useDecompression) decorators.Add(decompressor);using (MemoryStream mstream = CreateStream(File.ReadAllBytes(filepath), decorators))
{
result = (T)dcs.ReadObject(mstream);
}
-
Disposing a
MemoryStream
doesn't release any unmanaged resources. It simply sets some flags to indicate that future attempts to read or write the stream should throw an exception.protected override void Dispose(bool disposing)
{
try {
if (disposing) {
_isOpen = false;
_writable = false;
_expandable = false;
// Don't set buffer to null - allow TryGetBuffer, GetBuffer & ToArray to work.
#if FEATURE_ASYNC_IO
_lastReadTask = null;
#endif
}
}
finally {
// Call base.Close() to cleanup async IO resources
base.Dispose(disposing);
}
}Reference Source[^] Despite the comment about the base method cleaning up async IO resources, it doesn't:
protected virtual void Dispose(bool disposing)
{
// Note: Never change this to call other virtual methods on Stream
// like Write, since the state on subclasses has already been
// torn down. This is the last code to run on cleanup for a stream.
}Reference Source[^] But I know what you mean - it doesn't feel right to omit the
using
statement. :) Perhaps a helper method to create the stream might help to hide the unpleasantness?private static MemoryStream CreateStream(byte[] rawBytes, IEnumerable<Func<MemoryStream, MemoryStream>> decorators)
{
var result = new MemoryStream(rawBytes);foreach (Func<MemoryStream, MemoryStream> decorator in decorators) { result = decorator(result); result.Position = 0; } return result;
}
...
var decorators = new List<Func<MemoryStream, MemoryStream>>();
if (useDecryption) decorators.Add(decryptor);
if (useDecompression) decorators.Add(decompressor);using (MemoryStream mstream = CreateStream(File.ReadAllBytes(filepath), decorators))
{
result = (T)dcs.ReadObject(mstream);
}
Thanks for another interesting, and challenging, response ! My "gut" is now telling me to switch to using byte-arrays wherever possible. Whether you gain anything (performance, memory economy) when shipping the raw data off to be encrypted and/or compressed by using a byte-array rather than a stream ... that's terra incognita to me :) ... but, I suspect that as I research the various tools that will come into focus. cheers, Bill
«While I complain of being able to see only a shadow of the past, I may be insensitive to reality as it is now, since I'm not at a stage of development where I'm capable of seeing it. A few hundred years later another traveler despairing as myself, may mourn the disappearance of what I may have seen, but failed to see.» Claude Levi-Strauss (Tristes Tropiques, 1955)
-
Thanks for another interesting, and challenging, response ! My "gut" is now telling me to switch to using byte-arrays wherever possible. Whether you gain anything (performance, memory economy) when shipping the raw data off to be encrypted and/or compressed by using a byte-array rather than a stream ... that's terra incognita to me :) ... but, I suspect that as I research the various tools that will come into focus. cheers, Bill
«While I complain of being able to see only a shadow of the past, I may be insensitive to reality as it is now, since I'm not at a stage of development where I'm capable of seeing it. A few hundred years later another traveler despairing as myself, may mourn the disappearance of what I may have seen, but failed to see.» Claude Levi-Strauss (Tristes Tropiques, 1955)
The benefits would probably be more obvious if you were passing around the base
Stream
class. That way, your methods could work with anything stream-like, and wouldn't be limited to byte arrays.private static Stream DecorateStream(Stream input, IEnumerable<Func<Stream, Stream>> decorators)
{
Stream result = input;foreach (Func<Stream, Stream> decorator in decorators) { result = decorator(result); } return result;
}
...
var decorators = new List>();
if (useDecryption) decorators.Add(decryptor);
if (useDecompression) decorators.Add(decompressor);using (Stream input = DecorateStream(File.OpenRead(filePath), decorators)))
{
result = (T)dcs.ReadObject(input);
}Now your code can work on the file in chunks, rather than having to read the whole thing into memory first.
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer