Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I have a StreamWriter which underlying stream is a FileStream. Will the following code guarantee that the FileStream also flushes its buffer into the actual file on the file system, or do I need to explicitly call Flush() on the FileStream?

using (var fs = new FileStream("blabla", FileMode.Append)) {
    using (var sw = new StreamWriter(fs)) {
        sw.WriteLine("Hello, I want to be flushed.");
        sw.Flush(); //I need this to also flush onto the file, not just to the FileStream
    }
}

As per MSDN, "Flushing the stream will not flush its underlying encoder unless you explicitly call Flush or Close", but I do not know if a FileStream can be considered an "underlying encoder".

Also, if I don't specify FileOptions.WriteThrough, am I guaranteed that the OS will eventually write the flushed line onto the disk even if the program crashes before the two streams have been closed (assuming for example no using {} blocks, only a call to Flush())?

In my scenario I need to leave the stream open (for logging) so I cannot use using {} blocks, but I would like to make sure data will always be written to the disk even if the program crashes. I can afford to lose data if there is a power shutdown and the OS has not flushed onto the disk, but otherwise I need the OS to eventually flush even if I never properly call Close() on the stream.

like image 971
Erwin Mayer Avatar asked Oct 24 '12 05:10

Erwin Mayer


People also ask

What does flush do in StreamWriter?

Clears all buffers for the current writer and causes any buffered data to be written to the underlying stream.

What is Filestream flush?

Flush() Clears buffers for this stream and causes any buffered data to be written to the file. Flush(Boolean) Clears buffers for this stream and causes any buffered data to be written to the file, and also clears all intermediate file buffers.

What is the difference between StreamWriter and TextWriter?

TextWriter is an abstract class, which means it cannot be instantiated using the new keyword. From the MSDN documentation: By default, a StreamWriter is not thread safe.

Do I need to flush MemoryStream?

You don't need to use Flush on the MemoryStream , as it's not buffering anything that is written to any other source. There is simply nothing to flush anywhere. The Flush method is only present in the MemoryStream object because it inherits from the Stream class.


1 Answers

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.


like image 86
Damien_The_Unbeliever Avatar answered Oct 16 '22 07:10

Damien_The_Unbeliever