.NET文件系统监视器 - 它是一个文件还是一个目录?

37

使用FSW能否确定文件或目录是否已被删除?


坦白地说,我不确定你能否做到。显而易见的解决方法是在启动时递归以构建目录列表。如果不在该列表中,则是一个文件。 - Steven Sudit
4
不是“C# FileSystemWatcher”,而是.NET FileSystemWatcher。它与所有.NET语言一样有效,不仅限于C#。 - John Saunders
1
我想到一个办法,如果你运行两个独立的FSW来监视同一目录,并且只在它们的NotifyFilter值不同时,这可能会起作用。 - Steven Sudit
Steven Sudit,我认为你误解了NotifyFilter。 - Ini
4个回答

43

这是 fletcher 的解决方案的简化和修正版本:

namespace Watcher
{
    class Program
    {
        private const string Directory = @"C:\Temp";
        private static FileSystemWatcher _fileWatcher;
        private static FileSystemWatcher _dirWatcher;

        static void Main(string[] args)
        {
             _fileWatcher = new FileSystemWatcher(Directory);
             _fileWatcher.IncludeSubdirectories = true;
             _fileWatcher.NotifyFilter = NotifyFilters.FileName;
             _fileWatcher.EnableRaisingEvents = true;
             _fileWatcher.Deleted += WatcherActivity;

            _dirWatcher = new FileSystemWatcher(Directory);
            _dirWatcher.IncludeSubdirectories = true;
            _dirWatcher.NotifyFilter = NotifyFilters.DirectoryName;
            _dirWatcher.EnableRaisingEvents = true;
            _dirWatcher.Deleted += WatcherActivity;

            Console.ReadLine();
        }

        static void WatcherActivity(object sender, FileSystemEventArgs e)
        {
            if(sender == _dirWatcher)
            {
                Console.WriteLine("Directory:{0}",e.FullPath);
            }
            else
            {
                Console.WriteLine("File:{0}",e.FullPath);
            }
        }
    }
}

我已经解决了其中的错误,但你确实比我先想到了这个想法。 - Steven Sudit
4
这种解决方案没有考虑到两个 FileSystemWatcher 实例在不同线程上运行。因此,如果监视的目录中有很多事件,你在应用程序中看到的事件顺序可能会有所不同 - 例如,你可能会记录到在一个尚不存在的目录中创建了文件,随后是创建该目录的事件。 - Paya
与Paya所说的类似:使用一个监视器,如果删除目录,则首先会收到文件的删除事件,最后是目录的删除事件。再次使用两个监视器,顺序不被保证,当您想要复制这些事件时,可能会遇到(较少的)麻烦... - mvermand
文件名的NotifyFilter并不包括已更改的文件,只包括新增或重命名的文件。我快要疯了,准备反编译以编写一个更好的FileSystemWatcher类。这太荒谬了,而且性能也非常差。 - Barry

1

我最初使用了“Path”函数,但后来在不删除的情况下,我通过Directory.Exists进行了修复。然而这并没有解决删除的情况。

bool isDirectory = Path.GetExtension(e.FullPath) == string.Empty;


if (e.ChangeType != WatcherChangeTypes.Deleted)
{
    isDirectory = Directory.Exists(e.FullPath);
}

1
您的问题只有在同一路径下存在相同名称的文件和目录时才有意义,例如没有扩展名的文件名或带有扩展名的目录。如果您的目录和文件遵循通常的约定,只需检查完整路径中是否存在扩展名(bool iSDirectory = Path.GetExtension(e.FullPath).Equals("");),这适用于文件/目录存在与否,因为该方法仅解析给定的路径并与文件没有任何连接。如果您必须处理我在开头提到的非传统问题,您可以检查该位置是否存在目录或文件。如果两者都不存在,则将它们视为已删除。如果其中一个存在,则将另一个视为已删除。您的查询意味着您在某个地方保留了文件和目录列表,因此,通过针对该列表进行检查,您可以决定如何处理。我认为这种方法比使用两个文件系统监视器来区分的解决方案更好。

在文件夹名称中不使用点号是一种常见的约定吗? - Ini

-1
你可以查询 FileSystemEventArgs.FullPath 属性来判断它是一个目录还是一个文件。
if (Path.GetFileName(e.FullPath) == String.Empty) 
{
    //it's a directory.
}

检查它是文件还是目录。


3
被删除了,所以这些电话会失败,对吧? - Steven Sudit
2
File.GetAttributes 方法对于已删除的文件会抛出 FileNotFoundException 异常。 - Phil Gan
2
@Yuriy:正如我一直在说的那样,事实并非如此。与其信任您对文档的解释或我的记忆,不如进行测试。我在“C:\abc”上设置了一个FSW,并创建了一个“def”子目录。我发现e.FullPath包含“C:\abc\def”。请注意缺少任何尾随反斜杠。 - Steven Sudit
1
我刚刚尝试了一下,当我试图删除一个文件夹时,它会返回文件夹名称,而不是空的。 - Bishoy Hanna
1
Steven Sudit - 这一点也不具有教育性。如果文件没有扩展名,就会失败。 - Itay Gal
显示剩余11条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接