web-dev-qa-db-fra.com

Comment définir un filtre pour FileSystemWatcher pour plusieurs types de fichiers?

Partout, je trouve ces deux lignes de code utilisées pour définir le filtre pour l'observateur du système de fichiers dans les exemples fournis.

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

Mais je veux que mon observateur surveille plus de types de fichiers, mais pas tous. Comment puis-je atteindre cet objectif:

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

J'ai essayé ces derniers:

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

Les deux n'ont pas fonctionné. Ce ne sont que des bases mais ça me manque. Merci..

60
nawfal

Il existe une solution de contournement.

L'idée est de surveiller toutes les extensions, puis dans l'événement OnChange, filtrer vers les extensions souhaitées:

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."); 
    } 
} 
50
Mrchief

Tu ne peux pas faire ça. La propriété Filter ne prend en charge qu'un seul filtre à la fois. De la documentation :

Utilisation de plusieurs filtres tels que *.txt|*.doc n'est pas pris en charge.

Vous devez créer un FileSystemWatcher pour chaque type de fichier. Vous pouvez ensuite les lier tous au même ensemble de 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);
}
80
Anders Abel

Pour développer la solution de Mrchief et 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
    }
}

Cela élimine le vérificateur d'expressions régulières (qui, à mon avis, est trop de frais généraux), et utilise Linq à notre avantage. :)

Modifié - Ajout d'une vérification nulle pour éviter une éventuelle NullReferenceException.

17
Joe the Coder

Un rapide coup d'œil dans le réflecteur montre que le filtrage est effectué en code .Net après que l'api Windows a signalé le changement de système de fichiers.

Je suggère donc que l'approche consistant à enregistrer plusieurs observateurs est inefficace, car vous mettez plus de charge sur l'API, ce qui provoque plusieurs rappels et un seul des filtres correspondra. Mieux vaut simplement enregistrer un seul observateur et filtrer les résultats vous-même.

15
pbls624

Vous pouvez également filtrer en utilisant FileInfo en le comparant à la chaîne de l'extension que vous recherchez.

Par exemple, le gestionnaire d'un événement de modification de fichier pourrait ressembler à:

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               
    }
}
3
jdhurst