Home > .NET, Miscellaneous > Don't forget to close StreamWriter

Don't forget to close StreamWriter

December 21, 2007

In the midst of all my testing, learning, and blogging, my employer occasionally expects me to write a little code. As a result, I’ve spent most of this week being a productive employee, so you’ll have to wait a little while longer for the LINQ articles. In the meantime, I wanted to share a bone head problem I ran into while working on this new project.

The new project is fairly straight forward: read some data from a database, analyze it, look for inconsistencies, correct the inconsistencies, update the database, log the changes in a text file. OK, there’s more going on, but this is the general gist of things.

Having completed the difficult bits, namely recognizing and correcting “user input irregularities”, I moved on to the seemingly mindless task of writing the before and after information to a log file. How many times have we all done this:

StreamWriter file = File.CreateText(logFileName);
foreach (var item in collection)
    file.WriteLine("Some Text");

Simple, right? I ran a test and opened the text file and all appeared to be well. A few tests later, while viewing the results in Excel 2007, I noticed that the last line was cut off. Surely the problem could not be with Excel, I thought, so I looked at the raw text file, and the last line was cut off so many characters in from the left.

Naturally, all sorts of questions start flying through my head. Can an open StreamWriter only handle so many lines? Or could it be a limitation on number of bytes? Is there some system or program memory setting I’m not aware of? The code was so simple that it had to be something more

But alas, a little digging quickly led me to the answer: it was in fact my code. I failed to Close the StreamWriter, and so there were bytes that even though I had issued WriteLine(), had not yet been saved (or flushed) to the Text file.

I added Close() and sure enough all my data was written to the text file.

StreamWriter file = File.CreateText(logFileName);
foreach (var item in collection)
    file.WriteLine("Some Text");
// Close the StreamWriter to flush all the data to the file!

It’s good once in a while to run into something like this: it keeps us humble. Like the Roman Generals of old it reminds us that “we are mortal”.

Cheers, and Merry Christmas.

Categories: .NET, Miscellaneous
  1. December 21, 2007 at 2:26 pm

    Hey, don’t do it!
    You should use using keyword or try/finally block here.

    using(StreamWriter file = File.CreateText(logFileName))
    foreach (var item in collection)
    file.WriteLine(“Some Text”);

  2. December 22, 2007 at 9:29 pm

    Hi Dmytro,

    What using buys you is that the StreamWriter object gets marked for disposal, which I now have to assume means that Close is called at the appropriate time. I agree that “using” is a good approach for many things, but since the Close is the last thing I do in this program I essentially get the same result. In this case, though, since I’m explicitly controlling the Close, I know that the file will be completed immediately. With using, assuming that it will properly complete the file, I have to wait until the GC decides to reclaim the object.

    I could wrap the code in a Try-Catch-Finally set, but that would not address the problem I encountered, so I would still want to issue the Close() statement in the finally block.

  3. December 23, 2007 at 5:25 am

    Hi Joel,

    First of all you should read manual. Why? Because you are not see differences between destructors and IDispose. In two words: all you said is about desctructor (objects being destroyed when GC wants), but if you are using using keyword, object will be destroyed just right after the block finished.

    Why your approach with Close method calling is wrong? Tell me, what will happen if WriteLine method will throw an exception? Right, you stream will not be closed. But in case of using keyword stream will be closed even if exception thrown. Do you see difference?

    Keep your eyes opened.

  4. December 24, 2007 at 8:07 pm

    Sure, I see your point: I didn’t really consider the Try-Catch block because in and of itself it does not address the problem I was addressing. I do see the difference in what you are saying, and I think you are correct that using is probably a better approach: ultimately though, the developer needs to ensure that the FileStream is properly closed. Try-Catch does not solve that problem.

  1. No trackbacks yet.
Comments are closed.
%d bloggers like this: