关闭没有Flush()的文件流

我可以在不调用Flush情况下关闭文件流(在C#中)吗? 我知道CloseDispose调用Flush方法。

MSDN不是100%明确,但Jon Skeet说“Flush”,所以在关闭/处置之前这样做。 它不会伤害,对吗?

FileStream.Close方法

先前写入缓冲区的任何数据都会在文件流关闭之前复制到文件中,因此在调用Close之前不必调用Flush。 在调用Close之后,对文件流的任何操作都可能引发exception。 在调用一次关闭后,如果再次调用则不执行任何操作。

处置不是很清楚:

此方法通过将任何更改写入后备存储并关闭流来释放资源来处理流。

备注:评论员可能是对的,从Flush中不是100%清楚:

覆盖实现缓冲区的流上的Flush。 使用此方法将任何信息从基础缓冲区移动到其目标,清除缓冲区或两者。 根据对象的状态,您可能必须修改流中的当前位置(例如,如果基础流支持搜索)。 有关其他信息,请参阅CanSeek。

使用StreamWriter或BinaryWriter类时,请不要刷新基本Stream对象。 而是使用类的Flush或Close方法,该方法确保首先将数据刷新到基础流,然后写入文件。

测试:

 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(); } 

我能说什么…所有文件都有文字 – 也许这只是太少的数据?

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(); } 

再一次 – 每个文件都有它的字节……对我来说,看起来它正在做我从MSDN上读到的内容:如果你在处理之前调用Flush或Close并不重要……对此有什么想法?

不必Close()/Dispose() Flush()上调用Flush()FileStream将为您执行此操作,您可以从其源代码中看到:

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); } } 

既然你已经声明你理解了关闭&dispose称为flush方法,如果它没有被用户代码明确调用,我相信(通过close而不刷新)你实际上想要有可能放弃FileStream所做的更改,如有必要。

如果这是正确的,单独使用FileStream将无济于事。 您需要将此文件加载到MemoryStream (或数组中,具体取决于您修改其内容的方式),然后在完成后决定是否要保存更改。

显然,问题在于文件大小。 FileStream使用有限大小的写缓冲区来加速操作,但一旦耗尽,就需要刷新更改。 由于.NET内存限制,您只能在内存中加载较小的文件,如果您需要完全保留它们。

更简单的替代方法是制作文件的磁盘副本 ,并使用普通的FileStream处理它。 完成后,如果您需要放弃更改,只需删除临时文件,否则将原始文件替换为修改后的副本。

我一直在跟踪一个新引入的错误,似乎表明.NET 4在流处理时不能可靠地刷新磁盘更改(与.NET 2.0和3.5不同,它总是可靠地执行)。

.NET 4 FileStream类在.NET 4中经过了大量修改,虽然Flush *()方法已被重写,但似乎已经忘记了.Dispose()。

这导致文件不完整。

FileStream包装在BufferedStream并在缓冲流之前关闭文件流。

 var fs = new FileStream(...); var bs = new BufferedStream(fs, buffersize); bs.Write(datatosend, 0, length); fs.Close(); try { bs.Close(); } catch (IOException) { } 

使用Flush()在大循环中是值得的。 当你必须在一个循环中读取和写入一个大文件时。 在其他情况下,缓冲区或计算机足够大,并且在没有制作一个Flush()之前关闭()并不重要。

示例:您必须阅读大文件(以一种格式)并将其写入.txt

  StreamWriter sw = .... // using StreamWriter // you read the File ... // and now you want to write each line for this big File using WriteLine (); for ( .....) // this is a big Loop because the File is big and has many Lines { sw.WriteLine ( *whatever i read* ); //we write here somrewhere ex. one .txt anywhere sw.Flush(); // each time the sw.flush() is called, the sw.WriteLine is executed } sw.Close(); 

这里使用Flush()非常重要; 因为否则每个writeLine都保存在缓冲区中,并且在缓冲区为frull或程序到达sw.close()之前不会写入它。

我希望这有助于理解Flush的function

我认为使用简单的using语句是安全的,它在调用GetBytes()之后关闭了流;

 public static byte[] GetBytes(string fileName) { byte[] buffer = new byte[4096]; using (FileStream fs = new FileStream(fileName)) using (MemoryStream ms = new MemoryStream()) { fs.BlockCopy(ms, buffer, 4096); // extension method for the Stream class fs.Close(); return ms.ToByteArray(); } }