c++ - 如何强制刷新文件

标签 c++ windows file io

假设我有以下代码:

#include <chrono>
#include <fstream>
#include <thread>

int main()
{
  std::ofstream f("test.log");

  int i = 0;
  while (true)
  {
    f << i++;
    f.flush();

    std::this_thread::sleep_for(std::chrono::milliseconds(100));
  }
}

(请注意,每次写入操作后我都会调用 flush)

我注意到此应用程序不会更新“test.log”文件的“上次修改时间”和“大小”属性,除非我右键单击此文件或打开它。

我猜这是由于内部缓冲(系统不想进行像磁盘实际 I/O 这样耗时的操作,除非被迫这样做)。我说得对吗?

我需要编写一个应用程序来监视其他应用程序创建的日志文件中的更改(我无法更改它们)。起初,我想到了 C# 中的 FileSystemWatcher 类,但我注意到它具有相同的行为(它不会触发相应的事件,除非文件在源应用程序中关闭或被正确强制更新- 在 Windows 资源管理器中单击该文件)。那我该怎么办?尽可能频繁地为我想要查找的每个文件调用 WinAPI 函数,例如 GetFileAttributes

最佳答案

这里有两个独立的东西。首先,文件 MFT 记录(相当于 inode)的最后修改时间 会在您每次写入时更新。

但是 FindFirstFile 和 friend 返回的信息不是来自文件,而是来自目录条目中缓存的信息。每当关闭通过该目录条目打开的文件时,此缓存都会更新。。这是大多数应用程序显示的信息,例如 Windows 资源管理器和命令提示符 DIR 命令。

如果您想知道文件何时更新,您需要执行与读取 MFT 记录(inode)的 Unix stat 操作等效的操作。这需要打开文件句柄,调用 GetFileInformationByHandle 并再次关闭句柄。

第二件事是有充分的理由不这样做。如果程序正在写入文件,则它可能正在写入过程中。因此,该文件可能处于无效(损坏)状态。为确保文件处于有效状态,您应该等待文件关闭。这就是您知道文件现在可以查看的方式。

一旦写入程序完成写入文件,目录条目将被更新并且 FileSystemWatcher 将显示文件。

如果您绝对确定要查看仍在写入过程中的文件的通知,那么您可以查看 USN 更改日志作为一个选项。我不知道这是否比目录条目更新,您将不得不对此进行调查。

关于c++ - 如何强制刷新文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38607754/

相关文章:

C++ boost::program_options 读取与 getopt_long 兼容的参数

c++ - 根据派生类参数选择基类模板参数

c++ - 转换为 Unicode 时提升属性树问题

c# - 如何获取 PictureBox 中 ImageRectangle 的尺寸?

c++ - 使用未分配的内存没有错误?

windows - 使用批处理启动服务器后关闭 cmd

c - 从二进制文件中逐行打印序列

c++ - float 或 double 类型取决于指针的大小

c - 从文件更新数组,在 C 中进行验证

java - 用 Java 编写视频文件