Как установить фильтр для FileSystemWatcher для нескольких типов файлов?

везде я нахожу эти две строки кода, используемые для установки фильтра для наблюдателя файловой системы в предоставленных образцах..

FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Filter = "*.txt";
//or
watcher.Filter = "*.*";

но я хочу, чтобы мой наблюдатель контролировать несколько типов файлов, но не все. Как я могу достичь этого:

//watcher.Filter = "*.txt" | "*.doc" | "*.docx" | "*.xls" | "*.xlsx";

Я попытался это:

 watcher.Filter = "*.txt|*.doc|*.docx|*.xls|*.xlsx"; 
 // and
 watcher.Filter = "*.txt;*.doc;*.docx;*.xls;*.xlsx*";

оба не работают. Это только основы, но я скучаю по нему. Спасибо..

5 ответов


есть решение.

идея состоит в том, чтобы следить за всеми расширениями, а затем в событии OnChange отфильтровать нужные расширения:

FileSystemWatcher objWatcher = new FileSystemWatcher(); 
objWatcher.Filter = "*.*"; 
objWatcher.Changed += new FileSystemEventHandler(OnChanged); 

private static void OnChanged(object source, FileSystemEventArgs e) 
{ 
    // get the file's extension 
    string strFileExt = getFileExt(e.FullPath); 

    // filter file types 
    if (Regex.IsMatch(strFileExt, @"\.txt)|\.doc", RegexOptions.IgnoreCase)) 
    { 
        Console.WriteLine("watched file type changed."); 
    } 
} 

вы не можете этого сделать. The Filter свойство поддерживает только один фильтр одновременно. От документация:

использование нескольких фильтров, таких как *.txt|*.doc не поддерживается.

вам нужно создать FileSystemWatcher для каждого типа файла. Затем вы можете привязать их все к одному набору FileSystemEventHandler:

string[] filters = { "*.txt", "*.doc", "*.docx", "*.xls", "*.xlsx" };
List<FileSystemWatcher> watchers = new List<FileSystemWatcher>();

foreach(string f in filters)
{
    FileSystemWatcher w = new FileSystemWatcher();
    w.Filter = f;
    w.Changed += MyChangedHandler;
    watchers.Add(w);
}

чтобы расширить решение Mrchief и jdhurst:

private string[] extensions = { ".css", ".less", ".cshtml", ".js" };
private void WatcherOnChanged(object sender, FileSystemEventArgs fileSystemEventArgs)
{
    var ext = (Path.GetExtension(fileSystemEventArgs.FullPath) ?? string.Empty).ToLower();

    if (extensions.Any(ext.Equals))
    {
        // Do your magic here
    }
}

Это устраняет проверку регулярных выражений (которая, на мой взгляд, слишком накладна) и использует Linq в наших интересах. :)

Edited-добавлена проверка null, чтобы избежать возможного исключения NullReferenceException.


быстрый взгляд в отражателе показывает, что фильтрация выполняется в коде .Net после того, как api windows сообщил об изменении файловой системы.

поэтому я бы предположил, что подход регистрации нескольких наблюдателей неэффективен, поскольку вы загружаете больше нагрузки на API, вызывая несколько обратных вызовов, и только один из фильтров будет соответствовать. Гораздо лучше просто зарегистрировать одного наблюдателя и отфильтровать результаты самостоятельно.


вы также можете фильтровать с помощью FileInfo на по сравнению со строкой расширения, которое вы ищете.

например, обработчик события изменения файла может выглядеть так:

void File_Changed(object sender, FileSystemEventArgs e)
    {
        FileInfo f = new FileInfo(e.FullPath);

        if (f.Extension.Equals(".jpg") || f.Extension.Equals(".png"))
        {
           //Logic to do whatever it is you're trying to do goes here               
        }
}