在 C 或 C++ 中使用 fsync() 保存二进制文件

Using fsync() for saving binary files in C or C++

我的电脑最近突然关机了。当我重新打开电源时,我发现我上次 运行 时写入的一些二进制文件已损坏。我调查了一下,发现这是因为使用 fwrite 写入的数据不能保证立即写入磁盘。有人告诉我,为了保存我的数据而不会在另一次突然断电的情况下丢失数据,我应该使用 fsync 函数。但它看起来像是 Unix/Linux only facility 位于 unistd.h。我在 Windows,如何在 Windows 上做相当于 fsync 的事情?

我想保护使用如下简单程序写入的数据 -

void WriteBinFile(float var1, float var2, float var3)
{
    FILE *fp;
    fopen_s(&fp, "filename.dat", "wb");
    fwrite((void*)&var1, sizeof(float), 1, fp);
    fwrite((void*)&var2, sizeof(float), 1, fp);
    fwrite((void*)&var3, sizeof(float), 1, fp);
    // fsync(fp) ??? No such function exists on Windows. Here I want a facility to write data to disk in non-volatile manner.
    fclose(fp);
}

P.S。为什么我没有 UPS 是一个漫长而无趣的 story.Also,我在 Windows 8.1 并使用 Visual Studio 2013。另外,由于突然电源而受到影响的文件中断包含 0 秒。其中一些充满了 0,而另一些则只充满了部分 0。我没有写0s到文件,所以这肯定是停电的结果

我可能是错的,但我相信 fflush(fp); 应该可以解决问题。

对于读完第一段就停止阅读的人,还有 个步骤。

  1. 致电fflush(fp)。这会将所有数据从 C stdio 缓冲区刷新到操作系统缓冲区。

  2. 使用How do I get the file HANDLE from the fopen FILE structure?

  3. 然后在 HANDLE 上调用 FlushFileBuffers。这会将 Windows OS 缓冲区中的所有数据刷新到磁盘上。

您要找的是FlushFileBuffers。在你的情况下,FlushFileBuffers(fileno(fd)).

Windows 中的另一个有用习语由 close(dup(fd)) 给出,或者在您的情况下 close(dup(fileno(fp)))。这会刷新目录条目,以便文件大小对于不断增长的文件来说是正确的。否则目录仅在文件关闭时更新。