2

如何从 Node.js 中找出系统的 mtime 分辨率?

为什么我要问

在 Node.js 中,fs.watch有时会发出重复change事件。为了避免采取多余的操作,通常使用这样的代码(来自 CoffeeScript 的coffee实用程序):

  if event is 'change'
    fs.stat source, (err, stats) ->
      throw err if err
      return if stats.size is prevStats.size and
        stats.mtime.getTime() is prevStats.mtime.getTime()
      prevStats = stats
      ...

这就是问题所在:在 OS X 下,由于底层 HFS+ 文件系统,mtime分辨率只有 1 秒。也就是说,mtime.getTime()值的形式为

1322068921000

因此,每当在 1 秒内发生两次更改时,第二次更改就有可能不会影响文件的mtime. 多亏了stats.size检查,如果第二次更改对文件大小没有影响,这只是一个问题。不过,这仍然是个问题。

change一个可靠的解决方案是按 mtime 间隔“去抖动”事件;即在 OS X 下,当 achange发生时,我会等待 1 秒对其采取行动(从而将可能具有相同的所有更改事件mtime组合在一起)。但是我想在每个文件系统下将事件延迟尽可能短的时间,而不是采用最大的公分母。

4

2 回答 2

1

迭代某个目录(如 /tmp)中的所有文件并执行类似的操作

files.forEach(function(filename) {
    sum += fs.statSync(filename).mtime % 1000;
});

if (sum == 0) {
   // supports only 1 second resolution
} 

有点hacky,我知道。

于 2011-11-23T19:03:37.797 回答
1

在编写一些 Java 代码时,我遇到了同样的问题。这个问题超越了 Node.js,因为大多数语言在处理文件时都有类似的 API(并且都受到文件系统特定约束的限制)。Linux 中的其他文件系统也有同样的问题(1s 时间戳粒度),以及适用于 Windows 的旧 FAT32。

一个 hacky 解决方案是在读取文件(或发送文件事件)之前将文件的 mtime 实际设置回一秒。这样,如果在同一粒度窗口(本例中为 1 秒)内发生另一个修改,则新的 mtime 将不同,您将能够检测到修改。

如果没有其他应用程序正在使用该文件的 mtime,这应该可以正常工作,否则它很可能会干扰它们的操作。实际上,这是一种解决方法,不是正确的解决方案。尽管如此,我发现它在某些场景中很有用,例如,对于我的 Java 代码的自动化测试(测试会快速连续地修改文件,比实际使用中自然发生的要多)。

于 2014-06-19T14:22:42.210 回答