【问题标题】:Keeping track of file name changes跟踪文件名更改
【发布时间】:2012-06-23 19:18:52
【问题描述】:

我正在尝试编写一个基本的同步程序来在两个目录之间复制文件。

计划是拥有某种已经复制的文件的数据库,这样当程序扫描目录时,它可以挑选出它已经复制的内容以及需要再次复制的内容,即修改过的文件或新文件。

我不知道如何解决的一个问题是我应该如何处理由用户重命名的文件。我怎么知道重命名的文件实际上与数据库中列出的文件相同,尽管名称不同。是否有程序可以提取的基础文件 ID?我希望代码是可移植的,因此考虑到文件系统会有所不同,这可能会使这变得更加困难。

我想我可以记下每个文件的大小和创建日期,并将这些信息保存在数据库中,以确定文件是否实际上只是重命名了。如果两个文件具有相同的信息大小/日期,我可以存储一个散列或其他东西来区分它们,但我不知道这样做的效率如何。

有什么建议吗? (我使用的是 C++/QT)

【问题讨论】:

  • 您需要支持哪些平台/文件系统?大多数文件系统确实为每个文件都有一个唯一的 ID,但访问它不会是可移植的(尽管可以将不可移植的代码限制在一个相当小的特定部分)。顺便说一句,我不记得了,但 Boost Filesystem 可能也有办法解决这个问题。
  • 真的只是 Windows/OSX。我会去 Boost 看看他们有没有什么东西。作为一个有趣的问题,你知道我如何访问 windows 文件 ID 吗?
  • 在 Windows 上,您将在从 GetFileInformationByHandle 获得的结构中使用 nFileIndexLow/nFileIndexHigh

标签: c++ file qt filesystems rename


【解决方案1】:

要跟踪给定文件夹中文件的更改在您的应用程序运行时,请参阅QFileSystemWatcher,您可以在调用QFileSystemWatcher::addPath("directory/to/watch/") 后跟踪目录中的所有文件更改:

fileChanged() 信号在文件被修改时发出, 重命名或从磁盘中删除。同样,directoryChanged() 信号 当目录或其内容被修改或删除时发出。 请注意,QFileSystemWatcher 停止监视文件后 被重命名或从磁盘中删除,以及目录一旦被 从磁盘中删除。

为了在重命名文件后继续跟踪文件,只需再次使用QFileSystemWatcher::addPath() 重新启用观看即可。


当您的应用程序在重命名操作期间没有运行时,您必须查看文件的内容(如果您还想了解文件已被删除和复制回来,其中 linux 上的 inode / 其他文件系统类型上的任何内容都发生了变化)。

这可以使用 MD5 和来完成,但它需要您的应用程序读取整个文件,这对于大于 10 兆字节的文件可能会很慢。如果这个缺点是可以接受的,只需保存 QCryptographicHash::hash(file.readAll(), QCryptographicHash::Md5) 返回的 MD5 和。当然,在某些极端情况下您会遇到哈希冲突,但对于大多数应用程序来说,这应该不是问题。但请注意,可能您不会检测到内容的更改。另请注意,上面的简单单行是阻塞的,并且在计算 MD5 和之前将整个文件读入内存。使用 QCryptographicHash 提供的逐步 MD5 和计算(使用 addData()result() 代替)将文件“流式传输”到 MD5 计算中。

在读取整个内容之前比较文件大小而不是创建 MD5 总和在大多数情况下会起作用(更改导致文件大小相同的情况并不经常发生;在这种情况下,您可以回退到 MD5总和比较)。但是当你注意到一个变化之后,你无论如何都需要读取 MD5 和,以便能够检测到未来的变化!

【讨论】:

  • 对不起!我应该提到该程序只会按计划运行,因此用户可以在文件未运行时重命名文件。
  • @Box 我已经扩展了我的答案以涵盖这种情况。请记住,使用 ext 文件系统的 inode 等文件标识符取决于系统。
【解决方案2】:

在Unix下,可以使用stat获取文件的inode编号。

【讨论】:

    猜你喜欢
    • 2021-04-09
    • 1970-01-01
    • 2014-06-18
    • 2014-05-21
    • 1970-01-01
    • 1970-01-01
    • 2013-07-11
    • 2015-11-21
    • 2020-05-03
    相关资源
    最近更新 更多