StreamWriter.Flush()还会调用FileStream.Flush()吗?

时间:2012-10-24 05:56:47

标签: c# .net stream filestream flush

我有一个StreamWriter,其底层流是FileStream。以下代码是否保证FileStream还将其缓冲区刷新到文件系统上的实际文件中,或者我是否需要在Flush()上明确调用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
    }
}

根据MSDN,“刷新流不会刷新其底层编码器,除非您明确调用Flush或Close ”,但我不知道FileStream是否可以被视为“底层编码器“。

另外,如果我没有指定FileOptions.WriteThrough,我保证操作系统最终会将刷新的行写入磁盘,即使程序在两个流关闭之前崩溃(假设例如没有{{1阻止,只调用using {})?

在我的场景中,我需要打开流(用于记录),因此我不能使用Flush()块,但我想确保即使程序崩溃,数据也将始终写入磁盘。如果电源关闭并且操作系统没有刷新到磁盘上,我可以负担得起丢失数据,但是否则我需要操作系统最终刷新,即使我从未在流上正确调用using {}

2 个答案:

答案 0 :(得分:7)

是的,在Flush上调用StreamWriter会导致基础流被Flush编辑。 4.5版本调用私有Flush(bool,bool)函数,该函数以:

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

flushStream是第一个参数,this.stream是构建StreamWriter的流,而Flush()中的来电是Flush(true,true)。< / p>


(答案的较旧部分 - 我在回答时非常迂回。将答案中最相关的部分移到顶部)

在我可以找到它的文档中没有明确说明它,但是通过传递另一个流构造的任何流类应该被假定为“取得该流的所有权”(除非特别指出其他)。 / p>

也就是说,一旦您使用StreamWriter构建fs,就不应该自己对fs执行任何直接操作。


您从MSDN引用的部分与后面的句子有关:

  

这允许编码器保持其状态(部分字符),以便它可以正确编码下一个字符块。此方案影响UTF8和UTF7,其中某些字符只能在编码器接收到相邻字符后进行编码。

也就是说,您可能已将数据传递给Write,因此您已经为其提供了一些Unicode代理,但不是完整的字符。 Flush不会将这些代理人写入流中。只要你总是将格式良好的(完整的)字符串传递给Write,你就不需要关心这一点了。


答案 1 :(得分:4)

如果与使用块

一起使用,则可以保证流处理

使用一系列流,关闭最外面的流(在链的头部) i.e StreamWriter in your case 关闭整个 i.e FileStream < / p>

Flush方法强制立即写入内部缓冲区。当流为closed时自动调用刷新,因此您永远不需要执行以下操作

s.Flush();s.Close();

因此,当最顶端的流被关闭时,它会刷新,然后关闭它们也会刷新内容的流。

例如考虑此链

FileStream->GZipStream->StreamWriter

所以,关闭StreamWriter的那一刻

StreamWriter刷新并关闭。它还会关闭未定GZipStream

GzipStream刷新并关闭。它还会关闭基础FileStream

FileStream flushescloses