.Net MemoryStream close issue - c#

For a .Net MemoryStream object instance, do I need to close it explicitly after using it? Or no need to close it? Which is the best practices?
I am using VSTS2008 + .Net 3.5 + C#.

Better yet would be to use Using
using (MemoryStream ms = /*get it using your favorite ctor*/)
{
// use it here
// and now flush and copy to a file stream (for example)
ws.Flush();
byte[] buffer = ws.ToArray();
using (Stream stream = new FileStream("fileName", FileMode.Create))
stream.Write(buffer, 0, buffer.Length);
}
A little reminder - if you plan to write it all into another stream at the end, don't forget to Flush() (And don't leave the toilet seat up).
I use a StreamWriter around the ms, to write text data into the memory, and at the end put it all on disc in one go. (I can also change the example here to this case, if you'd like)

you should close it when you are done with it. The best practice is to close the stream in the finally section of a try-catch-finally block. you can get more information here:
http://msdn.microsoft.com/en-us/library/system.io.memorystream.aspx

Related

Issues with writing to a txt file after transmitting a small textfile using a C# TcpClient [duplicate]

I'm working on an assignment for a professor that is strict about LOC. For this reason I'd like to do the following:
(new StreamWriter(saveFileDialog.FileName)).Write(textBox.Text);
instead of
StreamWriter sw = new StreamWriter(saveFileDialog.FileName);
sw.Write(textBox.Text);
sw.Close();
In the first example I don't close the stream. Is this ok? Will it cause any security or memory problems?
You may not get any output, or incomplete output. Closing the writer also flushes it. Rather than manually calling Close at all, I'd use a using statement... but if you're just trying to write text to a file, use a one-shot File.WriteAllText call:
File.WriteAllText(saveFileDialog.FileName, textBox.Text);
Maybe your tutor is looking for:
File.WriteAllText(saveFileDialog.FileName, textbox.Text);
It's reasonable to prefer concise code, but not at the expense of readability or correctness.
Simplest solution without fout.Close() should be:
using (StreamWriter fout = new StreamWriter(saveFileDialog.FileName))
{
fout.Write(textBox.Text);
}
If you don't close it, you can't guarantee that it'll write out the last piece of data written to it. This is because it uses a buffer and the buffer is flushed when you close the stream.
Second, it will lock the file as open preventing another process from using it.
The safest way to use a filestream is with a using statement.
Short answer, the resources allocated for that operation will not be freed not to mention that it could pottentially lock that file.
Consider
using( var fout = new StreamWriter(saveFileDialog.FileName){ fout.write(textBox.Text); }
Any how GC will close it for you. But the thing is until the GC closes that stream you are unnecessary putting on hold to the resources
You can try with using blok in order to clean your no managed object
using (var streamWriter = new StreamWriter(saveFileDialog.FileName))
{
streamWriter.Write(textBox.Text);
}
It would be a memory hazard.
I would always use StreamWriter in a 'using' statement
using(StreamWriter fout = new StreamWriter(saveFileDialog.FileName)
{
fout.Write(textBox.Text);
}

Can't Use Stream.Write method while playing same file in MediaElement

So lets say I have a file which has around 2MB already downloaded and written which is being played using a MediaElement. So while the media is being played, I want to download and write the rest of the file.
If I use this method, I get an IOExecption error indicating the file is already in use.
using (Stream WriteStream = new FileStream(filename, FileMode.OpenOrCreate))
{
WriteStream.Seek(seekpos, SeekOrigin.Begin);
WriteStream.Write(buffer, 0, buffer.Length);
WriteStream.Close();
}
But if I use this method, it works fine.
FileStream1 = new System.IO.FileStream(filename, System.IO.FileMode.Append, System.IO.FileAccess.Write, System.IO.FileShare.ReadWrite);
FileStream1.Write(buffer, 0, buffer.Length);
So I could use the second method, but I want to be able to seek and write at certain positions which I can't do using the second method. So is there anyway in which I can use the first method. Does it have something to do with the FILEMODE or FILEACCESS?
Thanks :)
The closest you might get might be displayed here with what's known as a synchronized stream. Essentially, it's multiple threads acting on the same stream. You'd have to get the locking issue resolved, especially since you may have no way of making the MediaElement open the file with a shared lock.
Another approach might be to write to one file while the MediaElement plays from another. When the MediaElement's done with file A, play B and stream downloads to new file C. Repeat. Then, at the end, merge them together.
Never-mind I figured it out. I can use this to seek and write at any position. Stupid of me to not realise this.
FileStream1 = new System.IO.FileStream(filename, System.IO.FileMode.Append, System.IO.FileAccess.Write, System.IO.FileShare.ReadWrite);
FileStream1.Seek(seekpos,SeekOrigin.Begin);
FileStream1.Write(buffer, 0, buffer.Length);

Avoiding MemoryStream.ToArray() when using System.IO.Compression.ZipArchive

A helper method to turn a string into a zipped up text file:
public static System.Net.Mail.Attachment CreateZipAttachmentFromString(string content, string filename)
{
using (MemoryStream memoryStream = new MemoryStream())
{
using (ZipArchive zipArchive = new ZipArchive(memoryStream, ZipArchiveMode.Update))
{
ZipArchiveEntry zipArchiveEntry = zipArchive.CreateEntry(filename);
using (StreamWriter streamWriter = new StreamWriter(zipArchiveEntry.Open()))
{
streamWriter.Write(content);
}
}
MemoryStream memoryStream2 = new MemoryStream(memoryStream.ToArray(), false);
return new Attachment(memoryStream2, filename + ".zip", MediaTypeNames.Application.Zip);
}
}
I was really hoping to avoid turning the first memory stream into an array, making another memory stream on it to read it, and passing that to attachment. My logic was, why copy X megabytes to another place in memory to establish another stream pointing to the copy, when it's essentially just what we started out with.. It's the multi-megabyte equivalent of redundancy like if(myBool == true)
So I figured instead I would Seek back to the start of the first memory stream, and then attachment could just read that.. Or I would establish another memorystream pointing to the buffer of the first, and with the offset and length parameters set so it would know what to read
Neither of these approaches work out because it seems that ZipArchive only pushes data into the memory stream (in my case maybe) when control falls out of the using block and the ziparchive is disposed. Disposing it also disposes the MemoryStream and nearly everything (other than ToArray() and GetBuffer()) throw ObjectDisposedException.
Ultimately I can't seek it or get its length after the ZipArchive pumps data into it and before it pumps it in, the offset is usually zero and the length is definitely zero so the values are useless
Is there a nice optimal way, short of configuring my own over-large buffer (which then makes it non expandable by MemoryStream), to avoid having to burn up around 2x the memory bytes of the archive size with this method?
Most well designed streams and stream-users in .NET have an additional boolean parameter that can be used to instruct them to leave the "base stream" (terrible name) open when disposing.
This is ZipArchive's constructor:
public ZipArchive(
Stream stream,
ZipArchiveMode mode,
bool leaveOpen
)
There is no need for a second MemoryStream. You need to do two things:
Ensure, that the MemoryStream is not disposed before the last usage point. This is harmless. Disposing a MemoryStream does nothing helpful and for compatibility reasons can never do anything in the future. The .NET Framework has a very high compatibility bar. They often don't even dare to rename fields.
Seek to offset zero.
So remove the using around the MemoryStream and use the ctor for ZipArchive that allows you to leave the stream open.
Since the Attachment you are returning makes use of the MemoryStream you can't dispose it before exiting the method. Again, this is harmless. The only negative point is that the code becomes less obvious.
There's an entirely different approach: You can write your own Stream class that creates the bytes on demand. That way there is no need to buffer the string and ZIP bytes at all. This is much more work, of course. And it does not detract from the fact that the whole string must sit in memory at once, so it's still not a O(1) space solution.
public static System.Net.Mail.Attachment CreateZipAttachmentFromString(string content, string filename)
{
MemoryStream memoryStream = new MemoryStream();
using (ZipArchive zipArchive = new ZipArchive(memoryStream, ZipArchiveMode.Update, true))
{
ZipArchiveEntry zipArchiveEntry = zipArchive.CreateEntry(filename);
using (StreamWriter streamWriter = new StreamWriter(zipArchiveEntry.Open()))
{
streamWriter.Write(content);
}
}
memoryStream.Position = 0;
return new Attachment(memoryStream, filename + ".zip", MediaTypeNames.Application.Zip);
}

c# FileStream (FileAccess.Read) block other programs acess on .Close()

I have a program that copies video files, while they are being played.
More often than not, the video player (3rd party) is unable to access the file for around half a second (playback freezes) whenever I Close() the FileStream in my program.
From what I can tell, it won't matter if I use Dispose() instead of Close().
The file is copied to the new location as expected, so the playback freeze is the issue I need to solve, but frankly I do not know the specifics on how the 3rd party software reads the file.
I just can't wrap my head around why the problem appears exactly when I close the reading stream.
I would like to avoid having to postpone the copy process until the video player is done playing.
Any suggestions will be appreciated.
FileStream SourceFile = new FileStream(sourcePath, FileMode.Open, FileAccess.Read);
while(bytesLeftToCopy > 0)
{
int _BlockSize = 1024 * 1024;
byte[] _BlockBuffer = new byte[_BlockSize];
SourceFileBytes = SourceFile.Read(_BlockBuffer, 0, _BlockSize);
//you get the idea
}
SourceFile.Close();
Have you tried wrap your filestream into using construction? It automatically disposes the object after execution.
using (FileStream SourceFile = new FileStream(sourcePath, FileMode.Open, FileAccess.Read))
{
//read
}
Sorry to have bothered you guys, but it turns out that the problem was in the writing part of the program.
The guy who wrote this didn't flush the writing stream, which meant alot of data was cached when the read loop came to an end. Which in turn meant alot of system resources were used at Close() time.
I switched to the constructor (for the write stream) that accepts the FileOptions.WriteThough argument. This seems to have solved the problem.
Thanks for the suggestions you provided... I'll try to be more thorough when I create my next questions.

C# networkstream compression - Sharpziplib, DotNetZip, gzipstream all give errors on my stream

I have a pair of C# client-server programs that communicate using a networkstream.
Everything works fine as it is without compression.
Now I'd like to get the bandwidth-usage down, so I want to use a compressing wrapperstream around my networkstream.
I have tried SharpZipLib, DotNetZip, C#'s own GZipStream - but I can get none of them to work.
SharpZipLib has problems flushing, and applying the fix specified here: http://community.sharpdevelop.net/forums/p/7855/22139.aspx results in an exception "Header checksum illegal".
Using DotNetZip's DeflateStream results in a ZLibException("Bad state (invalid stored block lengths)");
GZipStream gives me a System.IO.InvalidDataException stating "The magic number in GZip header is not correct. Make sure you are passing in a GZip stream.".
The way I've implemented it is that everytime an array of byte has to be sent by my framework, I create a new Compression stream wrapper around the existing networkstream, write the bytes to the compression stream, and then flush, close & dispose it.
This to make sure that each WriteMessage(byte[] blah) uses it's own state-independent compressionstream that will be flushed immediately.
I've taken care to not let any of the streams close the original network stream.
using (System.IO.Stream outputStream = CreateOutputStreamWrapper(_networkStream))
{
outputStream.Write(messageBytes, 0, messageBytes.Length);
outputStream.Flush();
outputStream.Close();
outputStream.Dispose();
}
Basicly, my DecompressionStream is created as follows (optionals commented out)
protected System.IO.Stream CreateInputStreamWrapper(System.IO.Stream inInputStream)
{
//return new DeflateStream(inInputStream, CompressionMode.Decompress, true);
//return new BZip2InputStream(inInputStream, true);
return new GZipStream(inInputStream, System.IO.Compression.CompressionMode.Decompress, true);
}
and started as
_inputStream.BeginRead(_buffer, 0, _buffer.Length, new AsyncCallback(ReceiveCallback), null);
then in the ReceiveCallback, the data is read, the stream is flushed, closed and disposed:
//Get received bytes count
var bytesRead = _inputStream.EndRead(ar);
_inputStream.Flush();
_inputStream.Close();
_inputStream.Dispose();
and immediately create a new inputStream by calling CreateInputStreamWrapper again.
So what's going on ?
Since all compression-stream implementations are failing with errors that come down to "there's an error in the datastream" I have a hunch it must be me and my code.
On the other hand, if I remove the compression and just use the networkstream there's no problem, which makes me think the problem must lie with the compression-code.
Does this sound familiar to anyone ?
And while we're at it, does anyone know of any (other) compression stream implementations that are suited to wrap around a networkstream ?
Just in case anyone else ever reads this, DotNetZip's ZLib streams have a FlushMode flag that enables you to set up flushing compatible for networking stuff ('Sync' and 'Full' modes).

Categories