Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Close a filestream without Flush()

Can I close a file stream without calling Flush (in C#)? I understood that Close and Dispose calls the Flush method first.

like image 525
HelpME Avatar asked Sep 11 '11 07:09

HelpME


People also ask

What does Filestream close () do?

Closes the current stream and releases any resources (such as sockets and file handles) associated with the current stream.

What does Streamwriter flush do?

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


2 Answers

MSDN is not 100% clear, but Jon Skeet is saying "Flush", so do it before close/dispose. It won't hurt, right?

From FileStream.Close Method:

Any data previously written to the buffer is copied to the file before the file stream is closed, so it is not necessary to call Flush before invoking Close. Following a call to Close, any operations on the file stream might raise exceptions. After Close has been called once, it does nothing if called again.

Dispose is not as clear:

This method disposes the stream, by writing any changes to the backing store and closing the stream to release resources.

Remark: the commentators might be right, it's not 100% clear from the Flush:

Override Flush on streams that implement a buffer. Use this method to move any information from an underlying buffer to its destination, clear the buffer, or both. Depending upon the state of the object, you might have to modify the current position within the stream (for example, if the underlying stream supports seeking). For additional information see CanSeek.

When using the StreamWriter or BinaryWriter class, do not flush the base Stream object. Instead, use the class's Flush or Close method, which makes sure that the data is flushed to the underlying stream first and then written to the file.

TESTS:

var textBytes = Encoding.ASCII.GetBytes("Test123"); using (var fileTest = System.IO.File.Open(@"c:\temp\fileNoCloseNoFlush.txt", FileMode.CreateNew)) {     fileTest.Write(textBytes,0,textBytes.Length); } using (var fileTest = System.IO.File.Open(@"c:\temp\fileCloseNoFlush.txt", FileMode.CreateNew)) {     fileTest.Write(textBytes, 0, textBytes.Length);     fileTest.Close(); } using (var fileTest = System.IO.File.Open(@"c:\temp\fileFlushNoClose.txt", FileMode.CreateNew)) {     fileTest.Write(textBytes, 0, textBytes.Length);     fileTest.Flush(); } using (var fileTest = System.IO.File.Open(@"c:\temp\fileCloseAndFlush.txt", FileMode.CreateNew)) {     fileTest.Write(textBytes, 0, textBytes.Length);     fileTest.Flush();     fileTest.Close(); } 

What can I say ... all files got the text - maybe this is just too little data?

Test2

var rnd = new Random(); var size = 1024*1024*10; var randomBytes = new byte[size]; rnd.NextBytes(randomBytes); using (var fileTest = System.IO.File.Open(@"c:\temp\fileNoCloseNoFlush.bin", FileMode.CreateNew)) {     fileTest.Write(randomBytes, 0, randomBytes.Length); } using (var fileTest = System.IO.File.Open(@"c:\temp\fileCloseNoFlush.bin", FileMode.CreateNew)) {     fileTest.Write(randomBytes, 0, randomBytes.Length);     fileTest.Close(); } using (var fileTest = System.IO.File.Open(@"c:\temp\fileFlushNoClose.bin", FileMode.CreateNew)) {     fileTest.Write(randomBytes, 0, randomBytes.Length);     fileTest.Flush(); } using (var fileTest = System.IO.File.Open(@"c:\temp\fileCloseAndFlush.bin", FileMode.CreateNew)) {     fileTest.Write(randomBytes, 0, randomBytes.Length);     fileTest.Flush();     fileTest.Close(); } 

And again - every file got its bytes ... to me it looks like it's doing what I read from MSDN: it doesn't matter if you call Flush or Close before dispose ... any thoughts on that?

like image 148
Random Dev Avatar answered Sep 21 '22 22:09

Random Dev


You don't have to call Flush() on Close()/Dispose(), FileStream will do it for you as you can see from its source code:

http://referencesource.microsoft.com/#mscorlib/system/io/filestream.cs,e23a38af5d11ddd3

    [System.Security.SecuritySafeCritical]  // auto-generated     protected override void Dispose(bool disposing)     {         // Nothing will be done differently based on whether we are          // disposing vs. finalizing.  This is taking advantage of the         // weak ordering between normal finalizable objects & critical         // finalizable objects, which I included in the SafeHandle          // design for FileStream, which would often "just work" when          // finalized.         try {             if (_handle != null && !_handle.IsClosed) {                 // Flush data to disk iff we were writing.  After                  // thinking about this, we also don't need to flush                 // our read position, regardless of whether the handle                 // was exposed to the user.  They probably would NOT                  // want us to do this.                 if (_writePos > 0) {                     FlushWrite(!disposing); // <- Note this                 }             }         }         finally {             if (_handle != null && !_handle.IsClosed)                 _handle.Dispose();              _canRead = false;             _canWrite = false;             _canSeek = false;             // Don't set the buffer to null, to avoid a NullReferenceException             // when users have a race condition in their code (ie, they call             // Close when calling another method on Stream like Read).             //_buffer = null;             base.Dispose(disposing);         }     } 
like image 33
Dmitry Bychenko Avatar answered Sep 19 '22 22:09

Dmitry Bychenko