我有一个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 {}
。
答案 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 flushes
和closes