【问题标题】:How should I poll a large number of files for changes?我应该如何轮询大量文件以进行更改?
【发布时间】:2011-08-26 11:30:22
【问题描述】:

我想轮询文件系统是否有任何更改、添加或删除的文件或子目录。应快速检测所有变化,但不对机器施加压力。操作系统是 Windows >= Vista,观察到的部分是本地目录。

通常情况下,我会求助于 FileSystemWatcher,但这会导致尝试观看同一地点的其他程序(主要是 Windows 资源管理器)出现问题。另外,我听说 FSW 即使对于本地文件夹和大缓冲区也不是很可靠。

我遇到的主要问题是文件和目录的数量可能非常大(猜测 7 位)。简单地每秒检查所有文件确实会明显影响我的机器。

我的下一个想法是每秒检查整棵树的不同部分以减少整体影响,并可能添加一种启发式方法,例如检查快速连续频繁更改的文件。

我想知道这种问题是否存在模式,或者是否有人遇到过这种情况。

【问题讨论】:

  • 所有子文件夹都在一个根目录下吗?您在使用 Windows 资源管理器时遇到了哪些问题?这是确保您不会错过任何消息的模式。 stackoverflow.com/questions/4967095/…
  • @adrianm:是的,同一个根。 --- 当一个受监控的文件夹被更改时,资源管理器没有更新它的视图,我想是因为 FSW 偷了它的事件。

标签: .net filesystems polling filesystemwatcher


【解决方案1】:

我们使用 C# 实现了类似的功能。 FileSystemWatcher 对于大型目录树效率低下。

我们的替代方案是使用 FSNodes,这是我们创建的结构,使用以下 Windows API 调用:

    [StructLayout(LayoutKind.Sequential)]
        private struct FILETIME
    {
        public uint dwLowDateTime;
        public uint dwHighDateTime;
    };

    [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
        private struct WIN32_FIND_DATA
    {
        public FileAttributes dwFileAttributes;
        public FILETIME ftCreationTime;
        public FILETIME ftLastAccessTime;
        public FILETIME ftLastWriteTime;
        public uint nFileSizeHigh;
        public uint nFileSizeLow;
        public int dwReserved0;
        public int dwReserved1;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst=MAX_PATH)]
        public string cFileName;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst=MAX_ALTERNATE)]
        public string cAlternate;
    }

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool FindClose(IntPtr hFindFile);

    [DllImport("kernel32", CharSet=CharSet.Unicode)]
    private static extern IntPtr FindFirstFile(
        string lpFileName, out WIN32_FIND_DATA lpFindFileData);

    [DllImport("kernel32", CharSet=CharSet.Unicode)]
    private static extern bool FindNextFile(
        IntPtr hFindFile, out WIN32_FIND_DATA lpFindFileData);

我们所做的是静态处理。我们将元数据树保存在磁盘上,并将存储的目录树与加载的目录树进行比较,搜索已修改(基于其时间戳(更快)或文件哈希)。此外,我们可以管理删除、添加和移动,甚至移动修改的文件(也基于文件哈希)。

这个实现与每个 POLL_TIME 执行它的守护进程混合在一起,对我们是有效的。希望对您有所帮助。

【讨论】:

  • 您能解释一下您是如何使用 Win32 API 调用的吗?
  • FindFirstFile 在目录中搜索名称与特定名称匹配的文件或子目录(如果使用通配符,则为部分名称)。 FindNextFile 继续从先前调用 FindFirstFileFindFirstFileEx 函数开始的文件搜索。关闭由FindFirstFile(和其他)函数打开的文件搜索句柄。我建议使用谷歌搜索来更好地理解 API。
【解决方案2】:

如果是本地机器,我最好的猜测是使用 USN 日志,你有管理员权限并且分区是 NTFS。 USN 期刊非常快速和可靠。这是一个很长的话题,这个链接解释了一切: http://www.microsoft.com/msj/0999/journal/journal.aspx

【讨论】:

    【解决方案3】:

    对于 *nix 环境,您可以使用 inotify https://github.com/rvoicilas/inotify-tools/wiki/,它在我有限的研究中非常有用。可能有一个版本可以在我没有经验的 windows 上工作......快速谷歌搜索让我找到了一个名为 jnotify http://jnotify.sourceforge.net/ 的 java 克隆,它被宣传可以在 windows 上工作,所以它可能值得一试。

    【讨论】:

      猜你喜欢
      • 2021-05-23
      • 2018-08-11
      • 2014-05-08
      • 1970-01-01
      • 1970-01-01
      • 2020-02-12
      • 1970-01-01
      • 2011-01-04
      • 1970-01-01
      相关资源
      最近更新 更多