代码之家  ›  专栏  ›  技术社区  ›  Stefan Schultze

如何确保所有数据都已物理写入磁盘?

  •  18
  • Stefan Schultze  · 技术社区  · 16 年前

    我知道.NET FileStream的Flush方法仅将当前缓冲区写入磁盘,但这取决于Windows的磁盘驱动程序和硬盘固件。这并不能保证数据实际写入磁盘。

    有没有一个.NET或Win32方法可以给我这个保证?因此,如果在调用此方法后的一纳秒内出现功率损失,我仍然可以确保一切正常?

    6 回复  |  直到 16 年前
        1
  •  17
  •   jimvfr    12 年前

    Stefan S.说:

    我知道.NET FileStream的Flush方法只将当前缓冲区写入磁盘

    否,.NET FileStream的刷新只将.NET缓冲区写入操作系统缓存,而不将操作系统缓存刷新到磁盘。遗憾的是,这个类上的MSDN文档没有这样说。对于.NET<4.0,您必须调用Flush+Win32的FlushFilebuffers:

    using System.Runtime.InteropServices;
    . . .
    
    // start of class:
    [DllImport("kernel32", SetLastError=true)]
    private static extern bool FlushFileBuffers(IntPtr handle);
    . . .
    
    stream.Flush();     // Flush .NET buffers to OS file cache.
    #pragma warning disable 618,612 // disable stream.Handle deprecation warning.
    if (!FlushFileBuffers(stream.Handle))   // Flush OS file cache to disk.
    #pragma warning restore 618,612
    {
      Int32 err = Marshal.GetLastWin32Error();
      throw new Win32Exception(err, "Win32 FlushFileBuffers returned error for " + stream.Name);
    }
    

    2012年9月11日更新:MS错误报告 here 说它坏了,然后修复了,但没有说它是用什么版本或服务包修复的!听起来这个bug是因为如果内部.NET FileStream缓冲区为空,则刷新(true)什么也没做??

        2
  •  9
  •   Pavel Radzivilovsky    14 年前

    在窗户下面,看 FlushFileBuffers

        3
  •  4
  •   Marc Gravell    16 年前

    计算机 几年前,你将不得不希望磁盘能正常工作。

    事务性文件系统从未真正实现-p当然,您可以考虑使用数据库作为后端,并使用其事务系统?

    旁白:请注意,并非所有流都能保证 Flush() GZipStream etc保留未提交数据的工作缓冲区,即使在刷新之后也是如此——这是使其刷新的唯一方法 每件事 Close()

        4
  •  3
  •   Adi Lester    12 年前

    我注意到.NET 4#Flush(true)实际上并没有写入磁盘。我们在损坏的数据方面遇到了奇怪的问题,我发现了这个问题 bug report 在MS站点上:

    1. 将一组数据写入磁盘
    2. fs.Flush(true)
    3. 使用win32 API FlushFileBuffers . 这需要很长时间。

    我正在切换到win32 FlushFileBuffers调用。。。

        5
  •  0
  •   MSH    8 年前

    FileOptions.WriteThrough 而不是选择。

        6
  •  0
  •   Mickey2    5 年前

    将缓冲区的内容刷新到磁盘有一个简单的答案。

    这里有一个例子

    My.Computer.FileSystem.WriteAllText(yourfilename, "hello", False, System.Text.Encoding.ASCII)
    FileOpen(1, yourfilename, OpenMode.Input)
    FileClose(1)
    Reset()
    
        7
  •  -3
  •   Ayresome    16 年前

    有太多的抽象层次,无法绝对确保数据写入光盘,一直到硬件层次。