9

我有一个 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,我是否保证操作系统最终会将刷新的行写入磁盘,即使程序在两个流关闭之前崩溃(假设例如没有using {}块,只调用Flush())?

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

4

2 回答 2

9

是的,调用FlushStreamWriter导致底层流被Flush编辑。4.5版本调用了一个私有Flush(bool,bool)函数,其结尾为:

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

flushStream第一个参数在哪里,是构造this.stream的流,调用是。StreamWriterFlush()Flush(true,true)


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

它没有在我能找到的任何地方的文档中明确说明,但是任何通过将另一个流传递给它而构造的流类都应该被假定为“获取”该流的“所有权”(除非另有明确说明)。

也就是说,一旦你构建了StreamWriterusing fs,你就不应该对fs自己执行任何直接的操作。


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

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

也就是说,您可能已经将数据传递给Write这样的人,您已经给了它一些 Unicode 代理项,但不是一个完整的字符。Flush不会将这些代理项写入流。只要您始终将格式正确(完整)的字符串传递给Write,您就不必担心这一点。


于 2012-10-24T06:15:14.273 回答
4

如果与using block一起使用,则可以保证流处理!

使用一串流,关闭最外面的流(在链的头部)i.e StreamWriter in your case关闭整个地段i.e FileStream

Flush 方法强制立即写入内部缓冲区。流时会自动调用 Flush closed,因此您无需执行以下操作

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

因此,当最顶层的流关闭时,它会刷新,然后关闭它的底层流,这些流也刷新那里的内容。

例如考虑这个链

FileStream->GZipStream->StreamWriter

所以,当你关闭 StreamWriter

StreamWriter冲洗和关闭。它也关闭了undelyingGZipStream

GzipStream冲洗并关闭。它也关闭底层FileStream

文件流flushescloses

于 2012-10-24T06:04:27.487 回答