Differencebetween Streamwriter.Flush() and Streamwriter.Close()

What is the difference between StreamWriter.Flush() and StreamWriter.Close()?

StreamWriter.Flush() can be called any time you need to clear the buffer, and the stream will remain open.

StreamWriter.Close() is for closing the stream, at which point the buffer is also flushed.

But you shouldn't really need to call either of these. Any time I see a .Close() in code I take that as a code smell, because it usually means an unexpected exception could cause the resource to be left open. What you should do, is create your StreamWriter variable in a using block, like this:

using (var writer = new StreamWriter("somefilepath.txt"))
{
// write a bunch of stuff here
} // the streamwriter WILL be closed and flushed here, even if an exception is thrown.

Do I need to do StreamWriter.flush()?

Scratch the previous answer - I hadn't noticed that you were using two wrappers around the same stream. That feels somewhat risky to me.

Either way, I'd put the StreamWriter and BinaryWriter in their own using blocks.

Oh, and yes, it's legal to call ToArray() on the MemoryStream - the data is retained even after it's disposed.

If you really want to use the two wrappers, I'd do it like this:

using (MemoryStream stream = new MemoryStream())
{
using (StreamWriter normalWriter = new StreamWriter(stream))
using (BinaryWriter binaryWriter = new BinaryWriter(stream))
{
foreach(...)
{
binaryWriter.Write(number);
binaryWriter.Flush();
normalWriter.WriteLine(name); //<~~ easier to read afterward.
normalWriter.Flush();
}
}
return MemoryStream.ToArray();
}

I have to say, I'm somewhat wary of using two wrappers around the same stream though. You'll have to keep flushing each of them after each operation to make sure you don't end up with odd data. You could set the StreamWriter's AutoFlush property to true to mitigate the situation, and I believe that BinaryWriter currently doesn't actually require flushing (i.e. it doesn't buffer any data) but relying on that feels risky.

If you have to mix binary and text data, I'd use a BinaryWriter and explicitly write the bytes for the string, fetching it with Encoding.GetBytes(string).

difference between flush and close function in case of filewriter in java

flush() writes the content of the buffer to the destination and makes the buffer empty for further data to store but it does not closes the stream permanently. That means you can still write some more data to the stream.

But close() closes the stream permanently. If you want to write some data further, then you have to reopen the stream again and append the data with the existing ones.

Will StreamWriter.Flush() also call FileStream.Flush()?

Yes, calling Flush on StreamWriter will cause the underlying stream to be Flushed. The 4.5 version calls a private Flush(bool,bool) function, which ends with:

if (flushStream)
{
this.stream.Flush();
}

Where flushStream is the first parameter, this.stream is the stream that the StreamWriter was constructed on, and the call in Flush() is Flush(true,true).


(Older parts of answer - I was being very roundabout in answering. Moved most relevant part of answer to top)

It's not explicitly spelled out in the documentation anywhere I can find it, but any stream class that is constructed by passing it another stream should be assumed to "take ownership" of that stream (unless it's specifically called out otherwise).

That is, once you've constructed the StreamWriter using fs, you shouldn't perform any direct actions on fs yourself.


The part you quoted from MSDN relates to the later sentences:

This allows the encoder to keep its state (partial characters) so that it can encode the next block of characters correctly. This scenario affects UTF8 and UTF7 where certain characters can only be encoded after the encoder receives the adjacent character or characters.

That is, you may have passed data to Write such that you've given it some Unicode surrogates, but not a complete character. Flush will not write those surrogates to the stream. So long as you're always passing well formed (complete) strings to Write, you do not need to concern yourself about this.


Is there a benefit in closing StreamReader (or StreamWriter) when I close Stream explicitly?

You do need to close a StreamWriter (generally via the using block), or else data in its buffer could be lost.

Because both StreamReader and StreamWriter default to closing the stream automatically, if you want to eliminate one using block from your code, it should be the Stream that you remove from using.

If you can't do that, for example you've borrowed the Stream from elsewhere that doesn't want you to close it, then you must use the leaveOpen parameter you're already aware of. The reason that you can't just omit the using statement for a StreamReader/StreamWriter in order to leave it open, is that the garbage collector will still trigger some cleanup (although not as much) since the object is unreachable... only this will now occur at an unrelated time, creating an unpredictable bug that's very hard to find.

It is indeed ugly that you can't specify leaveOpen without explicitly controlling the buffer size, etc. May I suggest a helper method along the lines of StreamReader CreateStreamReaderLeaveOpen(Stream)?

Flush StreamWriter at the end of its lifetime

First of all, using a singleton creates problems in its own right, and this did not need another proof. Here, it's cleanup for a disguised global. The StreamWriter does not auto-flush on program end and according to the documentation,

You must call Close to ensure that all data is correctly written out to the underlying stream.

Thanks to an answer to "Self-closing StreamWriter singleton" from @PeterDuniho a possible solution could be changing the constructor to

private Foo()
{
this.os = System.IO.File.CreateText( "D:/tmp/test" );
System.AppDomain.CurrentDomain.ProcessExit +=
(sender, eventArgs) => this.os.Close();
}

Considering the problem of calling Close() in the destructor, I should not have ignored the "finalizers are not of much use anyway" written all over the place. In this case, as garbage collection does not use a specific order, the StreamWriter object has already been collected and cannot be closed in its resurrected zombie state.

Does .Disposing a StreamWriter close the underlying stream?

StreamWriter.Close() just calls StreamWriter.Dispose() under the bonnet, so they do exactly the same thing.
StreamWriter.Dispose() does close the underlying stream.

Reflector is your friend for questions like this :)



Related Topics



Leave a reply



Submit