Reputation: 18670
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.
Upvotes: 9
Views: 4798
Reputation: 32827
Streams disposal is guaranteed if used with using block!
With a chain of streams,closing the outermost stream(at the head of the chain) i.e StreamWriter in your case
closes the whole lot i.e FileStream
Flush method forces internal buffer to be written immediately.Flush is automatically called when stream is closed
,so you never need to do the following
s.Flush();s.Close();
So,the moment the most topmost stream is closed it flushes and then closes it underlying streams who also flush there content.
For example consider this chain
FileStream->GZipStream->StreamWriter
So,the moment you close the StreamWriter
StreamWriter
flushes and closes.It also closes undelying GZipStream
GzipStream
flushes and closes.It also closes underlying FileStream
FileStream flushes
and closes
Upvotes: 4
Reputation: 239824
Yes, calling Flush
on StreamWriter
will cause the underlying stream to be Flush
ed. 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.
Upvotes: 9