如何知道文件是否已被更改

How to know if files have been changed?

本文关键字:是否 何知道 文件      更新时间:2023-10-16

我正在编写一个自定义的c++程序,该程序仅在文件自上次复制以来在源代码中被更改时才复制文件。所以我需要知道我的特定文件夹中的文件是否被更改了。

我原本想在这些文件上计算SHA-1哈希值,但这可能意味着我必须在整个文件夹上执行此操作。另外,如果这些文件的大小是100GB怎么办?这意味着我必须在100GB的数据上计算SHA-1,这可能需要一些时间。

所以我很好奇是否有更好的方法来做到这一点?

你至少有几种可能性。

一种方法是使用NTFS更改日志来跟踪哪些文件被修改了。

每个文件都有一个与之相关联的"存档"标志。这通常由备份程序使用。每次写入文件时,都会设置该标志。当你复制/备份它时,你清除了标记。当您想要查看要复制/备份的文件时,只需检查标志是否已设置或清除即可。明显的问题:与其他备份程序冲突。

还有一个ReadDirectoryChangesW 1。但是,这只能检测在使用它的代码运行时发生的更改。要用它来跟踪变化,你需要设置一个一直在后台运行的服务来跟踪变化。根据文件及其修改方式的不同,即使这样,仍然有可能错过在启动期间(在服务开始执行之前)发生的更改。

我已经大致按照它们是否符合你的需求的降序列出了这些。,更改日志几乎肯定是最适合的,其次是存档标志,而ReadDirectoryChangesW(以相当大的差距)最不适合您的明显需求。


<一口>1. 还有一种较旧的FindFirstChangeNotification/FindNextChangeNotification,但它们不太通用,并且具有与ReadDirectoryChangesW相同的缺点。有一段时间,它们对于需要与Windows 95/98/SE兼容的代码很有用(因为这些代码不包括ReadDirectoryChangesW),但是已经有很多年没有一个好的理由使用它们了。

在其他答案的注释中,您已经声明您不能使用文件监视API(例如FindFirstChangeNotification),因为您的代码可能在更改发生时没有运行。

我建议多管齐下。

  1. 如果你的应用程序正在运行,使用文件监控api来检测新的更改。
  2. 在启动或出现新磁盘时,检查文件大小是否与以前相同。如果它不是,那么你知道你已经改变了。
  3. 如果文件大小相同,您可以使用文件的存档标志来确定它是否已更改。但是,存档标志很容易被用户更改,因此您可能不应该依赖它。
  4. 使用文件最后修改的时间戳。这可以由用户修改,但更难以做到。
  5. 使用散列来确定文件是否已更改。您选择的散列取决于检测更改的重要性。如果它不是关键的,像CRC32或MD5这样的东西就足够了。如果需要安全,可以考虑使用SHA-256。考虑将大文件分成小块。这样你就不必在得到"this changed"的结果之前散列整个文件。

这种分层的方法允许您在任何可能的情况下跳过昂贵的散列。

如果你想在"实时"中做到这一点,Windows有一个本地API。FindFirstChangeNotifcation ()