我想在文件系统中轮询任何已更改,添加或删除的文件或子目录。应尽快检测所有更改,但不要对机器施加压力。操作系统是Windows> = Vista,观察到的部分是本地目录。
通常情况下,我会使用FileSystemWatcher,但这会导致其他试图观看相同位置的程序出现问题(突出显示,Windows资源管理器)。另外,我听说即使对于本地文件夹和大缓冲区,FSW也不是真的可靠。
我遇到的主要问题是文件和目录的数量可能非常大(猜测为7位数)。只需每秒检查一次所有文件就会对我的机器产生明显的影响。
我的下一个想法是每秒检查整棵树的不同部分以减少整体影响,并可能添加一种启发式方法,例如检查更快地连续更改的文件。
我想知道是否存在此类问题的模式,或者是否有人遇到过这种情况。
答案 0 :(得分: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执行它的守护程序混合,对我们有效。希望它有所帮助。
答案 1 :(得分:1)
我最好的猜测是使用USN日志,如果它是本地机器,你有管理员权限,分区是NTFS。 USN期刊非常快速可靠。这是一个很长的topis,这个链接解释了一切: http://www.microsoft.com/msj/0999/journal/journal.aspx
答案 2 :(得分:0)
对于* nix环境,您可以使用inotify https://github.com/rvoicilas/inotify-tools/wiki/,这在我的有限研究中非常有用。可能有一个版本可以使用Windows,我没有经验...快速谷歌搜索引导我到一个名为jnotify http://jnotify.sourceforge.net/的java克隆,它被宣传为在Windows上工作,所以它可能值得尝试。 / p>