2011-08-26 59 views
8

我想轮询文件系统的任何更改,添加或删除的文件或子目录。应尽快检测所有更改,但不要对机器施加压力。操作系统是Windows> = Vista,观察部分是本地目录。我应该如何轮询大量文件以进行更改?

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

我的主要问题是文件和目录的数量可能会非常大(猜测7位数字)。每秒只需运行一次所有文件检查就会明显影响我的机器。

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

我想知道是否有这种问题的模式,或者如果有人有这种情况的经验。

+0

所有子文件夹是否在单个根目录下?你有什么样的问题与Windows资源管理器?这里有一个模式可以确保你不会错过任何消息。 http://stackoverflow.com/questions/4967095/c-predict-file-system-events-on-folder-delete/4968391#4968391 – adrianm

+0

@adrianm:是的,同一根。 ---当受监控的文件夹发生变化时,Explorer没有更新其视图,我想因为FSW偷走了它的事件。 – mafu

回答

3

我们使用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对我们都有效。希望能帮助到你。

+0

您能否介绍一下您如何使用Win32 API调用? – Cocowalla

+0

'FindFirstFile'在目录中搜索名称与特定名称匹配的文件或子目录(如果使用通配符,则使用部分名称)。 FindNextFile继续从前一次调用到FindFirstFile或FindFirstFileEx函数的文件搜索。关闭由FindFirstFile(和其他)函数打开的文件搜索句柄。我建议谷歌搜索更好地API。 –

相关问题