2011-08-06 18 views
48

todas partes que se encuentran estas dos líneas de código utilizan para establecer filtro para FileSystemWatcher en muestras proporcionadas ..¿Cómo establecer el filtro para FileSystemWatcher para varios tipos de archivos?

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

Pero yo quiero que mi vigilante para controlar más tipos de archivos, pero no todos. ¿Cómo puedo lograr esto:

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

he probado todas estas:

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

Ambos no funcionó. Esto es solo básico pero lo extraño. Gracias ..

Respuesta

35

Hay una solución.

La idea es estar atento a todas las extensiones y luego en el evento OnChange, filtrar a las extensiones deseadas:

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."); 
    } 
} 
+1

Una buena solución. ¿Sabes si esto afectará el rendimiento? –

+2

@Anders Abel: ¡Su suposición es tan buena como la mía!Si la carpeta observada recibe muchos cambios de archivos, y si la mayoría de esos cambios son para tipos de archivos _unwatched_, entonces incurrirá en una penalización. De lo contrario, no debería ser una gran sobrecarga. Al final, no hay nada más que puedas hacer, ¿verdad? (a menos que vaya a Win32 API) – Mrchief

+0

Haha. Mrchief, una buena solución. No estoy seguro si iría por eso. @Anders Abel ha dado otra solución. Ahora estoy confundido que marcar como respuesta .. :) – nawfal

72

No puede hacer eso. La propiedad Filter solo admite un filtro a la vez. Desde el documentation:

El uso de varios filtros como *.txt|*.doc no es compatible.

Debe crear un FileSystemWatcher para cada tipo de archivo. A continuación, se puede unir a todos para el mismo conjunto de controladores de eventos:

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); 
} 
+0

Ok, gracias por eso. Ni siquiera necesito esperar otras respuestas, ya que Microsoft dice cara a cara que no es posible. : x :) – nawfal

+0

Según la respuesta de pbls624, esto es menos ineficiente que registrarse para '*. *' y hacer el filtrado manualmente. –

2

También puede filtrar mediante el uso de FileInfo mediante la comparación de la cadena de la extensión que está buscando.

Por ejemplo, el controlador para un evento de archivo cambiado podría ser:

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    
     } 
} 
+0

Eso es lo que la respuesta de Mrchief es esencialmente. – nawfal

16

Para ampliar Mrchief de solución de 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 
    } 
} 

Esto elimina el comprobador de expresiones regulares (que en mi mente es demasiada sobrecarga), y utiliza Linq para nuestra ventaja. :)

Editado - Se agregó una comprobación nula para evitar posibles NullReferenceException.

+1

¿Por qué no usar solo "extensiones. Contiene (ext)"? Más simple. O incluso mejor, "extensiones. Contiene (ext, StringComparer.InvariantCultureIgnoreCase)" – nawfal

9

Un vistazo rápido en el reflector muestra que el filtrado se realiza en el código .Net después de que la API de Windows haya informado del cambio del sistema de archivos.

Por lo tanto, sugeriría que el enfoque de registrar varios observadores es ineficaz ya que está cargando más API provocando múltiples devoluciones de llamada y solo uno de los filtros coincidirá. Es mucho mejor simplemente registrar un solo observador y filtrar los resultados usted mismo.

+0

@vape Personalmente creo que esta respuesta agrega información muy valiosa a la pregunta. Puedo dar fe de su descubrimiento al ver el código fuente. – nawfal

Cuestiones relacionadas