Is it necessary to wrap StreamWriter in a using block? - c#

A few days ago I posted some code like this:
StreamWriter writer = new StreamWriter(Response.OutputStream);
writer.WriteLine("col1,col2,col3");
writer.WriteLine("1,2,3");
writer.Close();
Response.End();
I was told that instead I should wrap StreamWriter in a using block in case of exceptions. Such a change would make it look like this:
using(StreamWriter writer = new StreamWriter(Response.OutputStream))
{
writer.WriteLine("col1,col2,col3");
writer.WriteLine("1,2,3");
writer.Close(); //not necessary I think... end of using block should close writer
}
Response.End();
I am not sure why this is a valuable change. If an exception occurred without the using block, the writer and response would still be cleaned up, right? What does the using block gain me?

Nope the stream would stay open in the first example, since the error would negate the closing of it.
The using operator forces the calling of Dispose() which is supposed to clean the object up and close all open connections when it exits the block.

I'm going to give the dissenting opinion. The answer to the specific question "Is it necessary to wrap StreamWriter in a using block?" is actually No. In fact, you should not call Dispose on a StreamWriter, because its Dispose is badly designed and does the wrong thing.
The problem with StreamWriter is that, when you Dispose it, it Disposes the underlying stream. If you created the StreamWriter with a filename, and it created its own FileStream internally, then this behavior would be totally appropriate. But if, as here, you created the StreamWriter with an existing stream, then this behavior is absolutely The Wrong Thing(tm). But it does it anyway.
Code like this won't work:
var stream = new MemoryStream();
using (var writer = new StreamWriter(stream)) { ... }
stream.Position = 0;
using (var reader = new StreamReader(stream)) { ... }
because when the StreamWriter's using block Disposes the StreamWriter, that will in turn throw away the stream. So when you try to read from the stream, you get an ObjectDisposedException.
StreamWriter is a horrible violation of the "clean up your own mess" rule. It tries to clean up someone else's mess, whether they wanted it to or not.
(Imagine if you tried this in real life. Try explaining to the cops why you broke into someone else's house and started throwing all their stuff into the trash...)
For that reason, I consider StreamWriter (and StreamReader, which does the same thing) to be among the very few classes where "if it implements IDisposable, you should call Dispose" is wrong. Never call Dispose on a StreamWriter that was created on an existing stream. Call Flush() instead.
Then just make sure you clean up the Stream when you should. (As Joe pointed out, ASP.NET disposes the Response.OutputStream for you, so you don't need to worry about it here.)
Warning: if you don't Dispose the StreamWriter, then you do need to call Flush() when you're done writing. Otherwise you could have data still being buffered in memory that never makes it to the output stream.
My rule for StreamReader is, pretend it doesn't implement IDisposable. Just let it go when you're done.
My rule for StreamWriter is, call Flush where you otherwise would have called Dispose. (This means you have to use a try..finally instead of a using.)

If an exception occurs without the using block and kills the program, you will be left with openconnections. The using block will always close the connection for you, similiar to if you were to use try{}catch{}finally{}

Eventually, the writer will be cleaned up. When this happens is up to the garbage collector, who will notice that the Dispose for the command has not been called, and invoke it. Of course, the GC may not run for minutes, hours or days depending on the situation. If the writer is holding an exclusive lock on say, a file, no other process will be able to open it, even though you're long finished.
The using block ensures the Dispose call is always made, and hence that the Close is always called, regardless of what control flow occurs.

Wrapping the StreamWriter in a using block is pretty much equivalent of the following code:
StreamWriter writer;
try
{
writer = new StreamWriter(Response.OutputStream);
writer.WriteLine("col1,col2,col3");
writer.WriteLine("1,2,3");
}
catch
{
throw;
}
finally
{
if (writer != null)
{
writer.Close();
}
}
While you could very well write this code yourself, it is so much easier to just put it in a using block.

In my opinion it's necessary to wrap any class that implements IDisposable in a using block. The fact that a class implements IDisposable means that the class has resources that need to be cleaned up.

My rule of thumb is, if I see Dispose listed in intellisense, I wrap it in a using block.

the using block calls dispose() when it ends. It's just a handy way of ensuring that resources are cleaned up in a timely manner.

In almost every case, if a class implements IDisposable, and if you're creating an instance of that class, then you need the using block.

While it's good practice to always dipose disposable classes such as StreamWriter, as others point out, in this case it doesn't matter.
Response.OutputStream will be disposed by the ASP.NET infrastructure when it's finished processing your request.
StreamWriter assumes it "owns" a Stream passed to the constructor, and will therefore Close the stream when it's disposed. But in the sample you provide, the stream was instantiated outside your code, so there will be another owner who is responsible for the clean-up.

Related

Stream management after Environment.exit() invocation

I was searching in StackOverflow about try-finally and using blocks and what are the best practices on using them.
I read in a comment here that if your application is terminated abruptly by killing the process, a finally block will not get executed.
I was wondering, does the same apply to the using blocks? Will for example a stream get closed if a Environment.exit() call occurs inside the using block?:
//....
using (FileStream fsSource1 = new FileStream(pathSource,
FileMode.Open, FileAccess.Read))
{
//Use the stream here
Environment.exit();
}
As a second thought on it, and knowing that CLR Garbage Collector will probably take care of the stream objects if not closed properly in the program calls, is it considered necessary to close a stream in code, if the program gets terminated for sure after the completion of the stream usage?
For example, is there any practical difference between:
//....
using (FileStream fsSource1 = new FileStream(pathSource,
FileMode.Open, FileAccess.Read))
{
//Use the stream here
}
Environment.exit();
And:
//....
FileStream fsSource1 = new FileStream(pathSource, FileMode.Open, FileAccess.Read);
//Use the stream here
Environment.exit();
Or even the example mentioned before?
It shouldn't make a difference in the specific case of FileStream, modulo a tricky corner case when you used its BeginWrite() method. Its finalizer attempts to complete writing any unwritten data still present in its internal buffer. This is however not generally true, it will make a difference if you use StreamWriter for example.
What you are leaving up to the .NET Framework to decide is whether you truly meant to jerk the floor mat and seize writing the file. Or whether it should make a last-gasp attempt to flush any unwritten data. The outcome in the case of StreamWriter will tend to be an unpleasant one, non-zero odds that something is going to fall over when it tries to read a half-written file.
Always be explicit, if you want to make sure this does not happen then it is up to you to ensure that you properly called the Close() or Dispose() method. Or delete the file.

Force a file to be closed

I am reading, then writing to a text file. I do this in multiple parts of my program. After I'm done writing, I always close it (I use streamreader/writer). There is usually about 3 seconds between the close and the next time it's opened.
However, the second time I need to write to the same file, I always get an access denied error because another process is using it. At no point is any other process ever using it, and restarting my program lets me read from it.
This is the open/write/close code:
System.IO.StreamWriter file = new System.IO.StreamWriter(saveFileLocation.Text);
file.WriteLine(account);
file.Close();
Assuming there is no multi-threading then the issue is with proper disposal. The correct way to dispose of a stream or in general types that implement IDisposable is to wrap them in a using statement. The using statement ensures proper disposal and uses a finally block to ensure that the stream is closed even in exceptional circumstances.
using(var file = new System.IO.StreamWriter(saveFileLocation.Text))
{
//do work...
file.WriteLine(account);
}//when file goes out of scope it will close
Do this for all your streams.
use using statement or try{ }finally{ file.Close(); }
Are you sure an exception isn't being thrown, preventing close from being called? Either way this is better code:
using (System.IO.StreamWriter file = new System.IO.StreamWriter(saveFileLocation.Text))
{
file.WriteLine(account);
}

Writing to txt file with StreamWriter and FileStream

I ran into something interesting when using a StreamWriter with a FileStream to append text to an existing file in .NET 4.5 (haven't tried any older frameworks). I tried two ways, one worked and one didn't. I'm wondering what the difference between the two is.
Both methods contained the following code at the top
if (!File.Exists(filepath))
using (File.Create(filepath));
I have the creation in a using statement because I've found through personal experience that it's the best way to ensure that the application fully closes the file.
Non-Working Method:
using (FileStream f = new FileStream(filepath, FileMode.Append,FileAccess.Write))
(new StreamWriter(f)).WriteLine("somestring");
With this method nothing ends up being appended to the file.
Working Method:
using (FileStream f = new FileStream(filepath, FileMode.Append,FileAccess.Write))
using (StreamWriter s = new StreamWriter(f))
s.WriteLine("somestring");
I've done a bit of Googling, without quite knowing what to search for, and haven't found anything informative. So, why is it that the anonymous StreamWriter fails where the (non-anonymous? named?) StreamWriter works?
It sounds like you did not flush the stream.
http://msdn.microsoft.com/en-us/library/system.io.stream.flush.aspx
It looks like StreamWriter writes to a buffer before writing to the final destination, in this case, the file. You may also be able to set the AutoFlush property and not have to explicitly flush it.
http://msdn.microsoft.com/en-us/library/system.io.streamwriter.autoflush.aspx
To answer your question, when you use the "using" block, it calls dispose on the StreamWriter, which must in turn call Flush.
The difference between the two code snippets is the use of using. The using statement disposes the object at the end of the block.
A StreamWriter buffers data before writing it to the underlying stream. Disposing the StreamWriter flushes the buffer. If you don't flush the buffer, nothing gets written.
From MSDN:
You must call Close to ensure that all data is correctly written out to the underlying stream.
See also: When should I use “using” blocks in C#?

What happens if StreamReader or StreamWriter are not closed?

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);
}

Is it okay to not close StreamReader/StreamWriter to keep the underlying stream open?

I have a class that essentially wraps a Stream for reading/writing, but that stream is expected to be managed by the consumer of that class. For ease of use, I use StreamReader and StreamWriter classes to perform I/O operations on the stream. Normally I'd wrap the reader and writer in using blocks, but I want to avoid closing the reader and writer because doing so also closes the underlying stream and I have to keep it open.
Is it safe in terms of memory/resource management to not close a StreamReader/StreamWriter if I expect the underlying Stream to be managed by the caller? Will the reader and writer be garbage collected when the stream is explicitly closed elsewhere?
public class Wrapper
{
private Stream _underlyingStream;
public Wrapper(Stream underlyingStream)
{
_underlyingStream = underlyingStream;
}
public string GetValue()
{
_underlyingStream.Seek(0, SeekOrigin.Begin);
var reader = new StreamReader(_underlyingStream);
return reader.ReadToEnd(); // we're done, but the stream is not ours to close
}
}
If nobody closes the streams then ultimately the finalizer will be called which should call dispose and close them upon GC. But that's quite a crap-shoot resource-wise because it leaves whatever possibly-expensive resources allocated until GC. It could get worse the longer your object lives, especially if it survives collections to be promoted to gen 1 or even 2.
It sure would be nice if you could present something to your caller that isolates this. Perhaps you can cache something from the stream so you can close it while still serving the content to your caller?
EDIT after your edit: Now that I see your caller PASSES you a stream to operate on, my answer has to be different! It's very clear that your caller should be managing the stream's lifetime. I had the impression at first that your class created a stream and hoped the caller managed it.
The easiest way to solve this is to wrap the stream in your own class that derives from System.IO.Stream
Example:
http://csharptest.net/browse/src/Library/IO/NonClosingStream.cs
It is definetelly not ok.
read this from msdn
The close calls the Dispose method passing a true value.
Flushing the stream will not flush its underlying encoder unless you explicitly call Close.
Try to encapsulate all IO in a class.

Categories

Resources