Storing MemoryStream in Cache - c#

I've come across this code in one of my projects, which has a static function to return a MemoryStream from a file, which is then stored in Cache. Now the same class has a constructor which allows to store a MemoryStream in a private variable and later use it. So it looks like this:
private MemoryStream memoryStream;
public CountryLookup(MemoryStream ms)
{
memoryStream = ms;
}
public static MemoryStream FileToMemory(string filePath)
{
MemoryStream memoryStream = new MemoryStream();
ReadFileToMemoryStream(filePath, memoryStream);
return memoryStream;
}
Usage:
Context.Cache.Insert("test",
CountryLookup.FileToMemory(
ConfigurationSettings.AppSettings["test"]),
new CacheDependency(someFileName)
);
And then:
CountryLookup cl = new CountryLookup(
((MemoryStream)Context.Cache.Get("test"))
);
So I was wondering who should dispose the memoryStream and when? Ideally CountryLookup should implement IDisposable.
Should I even care about it?

It's slightly ugly - in particular, the MemoryStream is stateful, because it has the concept of the "current position".
Why not just store a byte array instead? You can easily build multiple MemoryStreams which wrap the same byte array when you need to, and you don't need to worry about the statefulness.
MemoryStreams don't usually require disposal, but I personally tend to dispose them out of habit. If you perform asynchronous operations on them or use them in remoting, I believe disposal does make a difference at that point. Byte arrays are just simpler :)

Related

Why do I need to flush and set the stream position to 0 in this serialization snippet?

Taken from here:
private static string SerializeToString<T>(T value)
{
using (var stream = new MemoryStream()) {
var formatter = new BinaryFormatter();
formatter.Serialize(stream, value);
stream.Flush();
stream.Position = 0;
return Convert.ToBase64String(stream.ToArray());
}
}
private static T DeserializeFromString<T>(string data)
{
byte[] b = Convert.FromBase64String(data);
using (var stream = new MemoryStream(b)) {
var formatter = new BinaryFormatter();
stream.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
}
}
Why do I need to flush and set the position to 0 in the serialize method, and seek in the deserialize method?
I removed them, they didn't affect anything.
I know that flushing means write whatever that's in the stream immediately.
But I don't know if it's necessary here... also not sure about the position and seek.
These samples contain unecessary code. The documentation for MemoryStream.ToArray (here) explicitly states that:
Writes the stream contents to a byte array, regardless of the Position
property.
Thus, we clearly don't need to set position. The flush is more debatable. It's very, very unlikely that memory stream would buffer under the hood, since it's just writing to a memory buffer anyway. However, I'm not sure that it's documented anywhere that memory stream won't buffer, so Flush() might be reasonable since we're calling ToArray() before disposing the stream. Another approach would be to call ToArray() outside the using block (we'd have to move the declaration of the variable out as well). This will work because ToArray() states that:
This method works when the MemoryStream is closed.
On the read side, you are creating a new stream, which starts at position 0 by default. Thus, there's no need for the Seek call.

Does XPathDocument use the memory stream it is constructed with after construction?

I have code like this:
// Take the xml message and turn it into an object
var bytes = Encoding.ASCII.GetBytes(message);
var memoryStream = new MemoryStream(bytes);
XPathDocument xPathDocument = new XPathDocument(memoryStream);
I realized that I don't clean up the MemoryStream anywhere. I was just going to change it to this:
// Take the xml message and turn it into an object
var bytes = Encoding.ASCII.GetBytes(message);
var memoryStream = new MemoryStream(bytes);
XPathDocument xPathDocument;
using(memoryStream)
{
xPathDocument = new XPathDocument(memoryStream);
}
But I was not sure if XPathDocument uses the MemoryStream internally after construction. (If so, I would need to wait and dispose it after I am all done with the XPathDocument.)
Does anyone know when I can dispose this MemoryStream?
No that's a good change. Once the stream is loaded into the xml, you don't need it any more.
Well I hope it's good, it's remarkably similar to a lot of the code I've written. :D
The entire Stream is read and load and so yes, you can Dispose the MemoryStream this way.
On the other hand, a MemoryStream doesn't really need to be Disposed, it's more the general principal. If it had been a FileStream or NetworkStream the using would have been critical.
If you're using the memorystream with using block anyway, it is better to limit the scope of the variable to the using block, that way you can be sure it will not be used outside of it, like this:
using (var memorystream = new MemoryStream(bytes))
{
xPathDocument = new XPathDocument(memoryStream);
}

MemoryStream instance timing help

Is it ok to instance a MemoryStream at the top of my method, do a bunch of stuff to it, and then use it?
For instance:
public static byte[] TestCode()
{
MemoryStream m = new MemoryStream();
...
...
whole bunch of stuff in between
...
...
//finally
using(m)
{
return m.ToArray();
}
}
Updated code
public static byte[] GetSamplePDF()
{
using (MemoryStream m = new MemoryStream())
{
Document document = new Document();
PdfWriter.GetInstance(document, m);
document.Open();
PopulateTheDocument(document);
document.Close();
return m.ToArray();
}
}
private static void PopulateTheDocument(Document document)
{
Table aTable = new Table(2, 2);
aTable.AddCell("0.0");
aTable.AddCell("0.1");
aTable.AddCell("1.0");
aTable.AddCell("1.1");
document.Add(aTable);
for (int i = 0; i < 20; i++)
{
document.Add(new Phrase("Hello World, Hello Sun, Hello Moon, Hello Stars, Hello Sea, Hello Land, Hello People. "));
}
}
My point was to try to reuse building the byte code. In other words, build up any kind of document and then send it to TestCode() method.
Technically, this is possible, but it's pointless. If you really want to avoid using the "using" statement around that code, just call Dispose() directly.
You should put the entire work that's using the MemoryStream into the using statement. This guarantees that the MemoryStream's Dispose method will be called, even if you receive an exception during your "whole bunch of stuff in between" code. The way you have it now, exceptions will prevent your MemoryStream from having Dispose() called on it.
The proper way to handle this would be:
public static byte[] TestCode()
{
MemoryStream m = new MemoryStream();
using(m)
{
// ...
// ...
// whole bunch of stuff in between
// ...
// ...
return m.ToArray();
}
}
Or, in the more common form:
public static byte[] TestCode()
{
using(MemoryStream m = new MemoryStream())
{
// ...
// ...
// whole bunch of stuff in between
// ...
// ...
return m.ToArray();
}
}
When seeing questions like these, I often wonder if we wouldn't have been better off using the Java model. There's an extraordinary amount of agony that .NET programmers suffer over that doggone IDisposable. After thousands of questions on SO (et al), it still remains poorly understood.
It is a memory stream. There's nothing that needs to be disposed when you use memory, the garbage collector already takes care of it. It is not some kind of special memory just because the class has a Dispose() method, there's only one kind. The other kind is wrapped by UnmanagedMemoryStream. The fact that MemoryStream inherits a do-nothing Dispose() method from Stream is a sad OOP liability.
It is up to you to decide to slovenly call a do-nothing method because it is there. Or you could take charge of your code and refuse to call methods that you know don't do anything useful now, nor will ever do anything useful for the rest of your career. Clearly I'm in the second camp, our life-expectancy must be better. I hope anyway. Then again, this post might have knocked a day off.

Equivalent of Java's "ByteBuffer.putType()" in C#

I am trying to format a byte array in C#, by porting a code from Java. In Java, the methods "buf.putInt(value);", buf.putShort, buf.putDouble, (and so forth) are used. However I don't know how to port this to C#. I have tried the MemoryStream class, but there is no method to put a specific type at the end of the byte array.
Question: What is the equivalent of Java's "ByteBuffer.putType(value)" in C#?
Thanks!
You can use a BinaryWriter and your MemoryStream:
MemoryStream stream = new MemoryStream();
using (BinaryWriter writer = new BinaryWriter(stream))
{
writer.Write(myByte);
writer.Write(myInt32);
writer.Write("Hello");
}
byte[] bytes = stream.ToArray();
Try the BinaryWriter class:
using (var binaryWriter = new BinaryWriter(...))
{
binaryWriter.Write(323);
binaryWriter.Write(3487d);
binaryWriter.Write("Hello");
}
You'll be wanting to use the BitConverter class. The main difference is that these methods return an array of bytes instead of altering an existing array.
(This is a replacement for the specific methods mentioned; for a replacement of the entire ByteBuffer class, see the other replies.)

Does my code properly clean up its List<MemoryStream>?

I've got a third-party component that does PDF file manipulation. Whenever I need to perform operations I retrieve the PDF documents from a document store (database, SharePoint, filesystem, etc.). To make things a little consistent I pass the PDF documents around as a byte[].
This 3rd party component expects a MemoryStream[] (MemoryStream array) as a parameter to one of the main methods I need to use.
I am trying to wrap this functionality in my own component so that I can use this functionality for a number of areas within my application. I have come up with essentially the following:
public class PdfDocumentManipulator : IDisposable
{
List<MemoryStream> pdfDocumentStreams = new List<MemoryStream>();
public void AddFileToManipulate(byte[] pdfDocument)
{
using (MemoryStream stream = new MemoryStream(pdfDocument))
{
pdfDocumentStreams.Add(stream);
}
}
public byte[] ManipulatePdfDocuments()
{
byte[] outputBytes = null;
using (MemoryStream outputStream = new MemoryStream())
{
ThirdPartyComponent component = new ThirdPartyComponent();
component.Manipuate(this.pdfDocumentStreams.ToArray(), outputStream);
//move to begining
outputStream.Seek(0, SeekOrigin.Begin);
//convert the memory stream to a byte array
outputBytes = outputStream.ToArray();
}
return outputBytes;
}
#region IDisposable Members
public void Dispose()
{
for (int i = this.pdfDocumentStreams.Count - 1; i >= 0; i--)
{
MemoryStream stream = this.pdfDocumentStreams[i];
this.pdfDocumentStreams.RemoveAt(i);
stream.Dispose();
}
}
#endregion
}
The calling code to my "wrapper" looks like this:
byte[] manipulatedResult = null;
using (PdfDocumentManipulator manipulator = new PdfDocumentManipulator())
{
manipulator.AddFileToManipulate(file1bytes);
manipulator.AddFileToManipulate(file2bytes);
manipulatedResult = manipulator.Manipulate();
}
A few questions about the above:
Is the using clause in the AddFileToManipulate() method redundant and unnecessary?
Am I cleaning up things OK in my object's Dispose() method?
Is this an "acceptable" usage of MemoryStream? I am not anticipating very many files in memory at once...Likely 1-10 total PDF pages, each page about 200KB. App designed to run on server supporting an ASP.NET site.
Any comments/suggestions?
Thanks for the code review :)
AddFileToManipulate scares me.
public void AddFileToManipulate(byte[] pdfDocument)
{
using (MemoryStream stream = new MemoryStream(pdfDocument))
{
pdfDocumentStreams.Add(stream);
}
}
This code is adding a disposed stream to your pdfDocumentStream list. Instead you should simply add the stream using:
pdfDocumentStreams.Add(new MemoryStream(pdfDocument));
And dispose of it in the Dispose method.
Also you should look at implementing a finalizer to ensure stuff gets disposed in case someone forgets to dispose the top level object.
Is the using clause in the AddFileToManipulate() method redundant and unnecessary?
Worse, it's destructive. You're basically closing your memory stream before it's added in. See the other answers for details, but basically, dispose at the end, but not any other time. Every using with an object causes a Dispose to happen at the end of the block, even if the object is "passed off" to other objects via methods.
Am I cleaning up things OK in my object's Dispose() method?
Yes, but you're making life more difficult than it needs to be. Try this:
foreach (var stream in this.pdfDocumentStreams)
{
stream.Dispose();
}
this.pdfDocumentStreams.Clear();
This works just as well, and is much simpler. Disposing an object does not delete it - it just tells it to free it's internal, unmanaged resources. Calling dispose on an object in this way is fine - the object stays uncollected, in the collection. You can do this and then clear the list in one shot.
Is this an "acceptable" usage of MemoryStream? I am not anticipating very many files in memory at once...Likely 1-10 total PDF pages, each page about 200KB. App designed to run on server supporting an ASP.NET site.
This depends on your situation. Only you can determine whether the overhead of having these files in memory is going to cause you problems. This is going to be a fairly heavy-weight object, though, so I'd use it carefully.
Any comments/suggestions?
Implement a finalizer. It's a good idea whenever you implement IDisposable. Also, you should rework your Dispose implementation to the standard one, or mark your class as sealed. For details on how this should be done, see this article. In particular, you should have a method declared as protected virtual void Dispose(bool disposing) that your Dispose method and your finalizer both call.
It looks to me like you misunderstand what Using does.
It's just syntactic sugar to replace
MemoryStream ms;
try
{
ms = new MemoryStream();
}
finally
{
ms.Dispose();
}
Your usage in AddFileToManipulate is redundant. I'd set up the list of memorystreams in the constructor of PdfDocumentManipulator, then have PdfDocumentManipulator's dispose method call dispose on all the memorystreams.
Side note. This really seems like it calls for an extension method.
public static void DisposeAll<T>(this IEnumerable<T> enumerable)
where T : IDisposable {
foreach ( var cur in enumerable ) {
cur.Dispose();
}
}
Now your Dispose method becomes
public void Dispose() {
pdfDocumentStreams.Reverse().DisposeAll();
pdfDocumentStreams.Clear();
}
EDIT
You don't need the 3.5 framework in order to have extension methods. They will happily work on the 3.0 compiler down targeted to 2.0
http://blogs.msdn.com/jaredpar/archive/2007/11/16/extension-methods-without-3-5-framework.aspx

Categories

Resources