Cocoa,FSEvents,kFSEventStreamCreateFlagFileEvents标志和“重命名”事件

时间:2011-11-29 16:40:26

标签: cocoa fsevents

我在我的一个小应用程序中使用FSEvents来同步我的应用程序的内容与硬盘上的内容(基本上,它是一个小图像查看器,我希望它的内容在更新时硬盘的内容发生了变化)

我使用kFSEventStreamCreateFlagFileEvents标志创建了我的流,但我很难弄清楚这些事件是由OS(或内核,或其他)生成的。不幸的是,没有关于事件的文档用这个标志生成......似乎它们是10.7的新手,但仍未记录。

所以,我的主要问题是“重命名”。当我正在进行简单的重命名时,会向我的回调发送2个kFSEventStreamEventFlagItemRenamed事件。一个包含旧文件名,第二个包含新文件名。重命名一批文件时会出现问题,这些事件可能不是顺序的。例如,它有以下几种情况:

  1. “file1” - > “new_file_1”
  2. “file2” - > “new_file_2”
  3. 我可能会按此顺序收到事件:

    1. “已重命名”/“file1”
    2. “renamed”/“file2”
    3. “已重命名”/“new_file_1”
    4. “已重命名”/“new_file_2”
    5. 当你遇到第二个重命名事件时似乎没有任何方法可以获得第一个重命名事件的ID ...所以我做的是:当收到“重命名”事件时,我做一个stat( )用文件名。如果stat成功返回,则表示它是新文件名。如果没有,这意味着它是旧的。我仍然没有办法链接这两个事件,但至少我可以通过删除旧文件并添加新文件来解决。

      所以,我基本上有两个问题:

      首先是:我完全失明了,没有看到通过fsevents正确捕捉“重命名”事件的明显方法吗?

      第二个i:我有时会有一个奇怪的错误,而不是只有2个重命名的事件,3个被发送!所以我得到一个文件添加两次...我不确定这是不是一个错误,或者如果这是因为我完全错过了使用kFSEventStreamCreateFlagFileEvents标志的fsevent API ...

      欢迎任何帮助,我完全没有想法解决这个问题!

3 个答案:

答案 0 :(得分:1)

由于这些事件只处理路径,因此您需要做一些额外的工作来处理重命名。一个选项是跟踪您感兴趣的文件的inode编号。因此,当您执行该stat调用时,还要记下inode编号并查看它是否与您正在跟踪的任何文件匹配。

请注意,操作系统可能会重复使用已删除文件的inode编号,因此根据它们作为唯一标识符并非绝对可靠。

答案 1 :(得分:0)

您可以通过从路径创建URL然后调用:

来获取文件ID
NSString *fileID = nil;

[url getResourceValue:&fileID forKey:NSURLFileResourceIdentifierKey error:&error]; //NS_AVAILABLE(10_7, 5_0);

(此标识符在系统重新启动时不会持久)

答案 2 :(得分:0)

您需要使用标志kFSEventStreamCreateFlagUseExtendedData(自OS X 10.13起可用)。使用该标志创建的流将包含事件文件的 inode 。这样,您可以检测到在报告的事件批次中发生的“重命名链”。

P.S。 macOS可能会将已删除文件的索引节点用于新创建的文件,尽管如果立即处理事件,则风险可以忽略。