关闭没有Flush()的文件流

Hel*_*pME 24 c# flush filestream

我可以Flush在不调用的情况下关闭文件流(在C#中)吗?我理解Close并首先Dispose调用该Flush方法.

Car*_*ten 17

MSDN并非100%明确,但Jon Skeet正在说"Flush",所以在关闭/处置之前这样做.它不会伤害,对吗?

FileStream.Close方法:

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

处理不是很清楚:

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

备注:评论员可能是对的,它不是100%清除Flush:

覆盖实现缓冲区的流上的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();
}
Run Code Online (Sandbox Code Playgroud)

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

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();
}
Run Code Online (Sandbox Code Playgroud)

再一次 - 每个文件都得到了它的字节......对我来说,它看起来像是在做我从MSDN上读到的内容:如果你在处理之前调用Flush或Close也没关系......对此有什么看法?

  • 是的 - 你可以在不调用`Flush()`的情况下调用`Close()`,但是你不能在没有刷新的情况下关闭:) (9认同)
  • 对阅读障碍牙医的建议:关闭前冲洗. (3认同)

Dmi*_*nko 12

不必Flush()Close()/Dispose(),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);
        }
    }
Run Code Online (Sandbox Code Playgroud)


Gro*_*roo 5

既然您已经声明您了解 close & dispose 会在用户代码未显式调用的情况下调用刷新方法,我相信(通过关闭而不刷新)您实际上希望有可能放弃对 a 所做的更改FileStream,如果必要的。

如果这是正确的,那么单独使用 aFileStream是没有帮助的。您需要将此文件加载到 a MemoryStream(或数组,具体取决于您修改其内容的方式),然后决定完成后是否要保存更改。

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

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


Lil*_*ver 5

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

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

这会导致文件不完整。

  • 并找到修复方法? (2认同)