example java nio java-7 watchservice

example - watchservice java



¿Por qué WatchService genera tantas operaciones? (4)

import java.io.*; import java.nio.file.*; public class Tmp { public static void main(String [] args) throws IOException { int count = 0; Path path = Paths.get("C://tmp//"); WatchService ws = null; try { ws = FileSystems.getDefault().newWatchService(); path.register(ws, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.OVERFLOW); } catch (IOException ioe) { ioe.printStackTrace(); } while(true) { WatchKey key = null; try { key = ws.take(); } catch(InterruptedException ie) { ie.printStackTrace(); } for(WatchEvent<?> event: key.pollEvents()) { switch(event.kind().name()) { case "OVERFLOW": System.out.println(++count + ": OVERFLOW"); break; case "ENTRY_MODIFY": System.out.println(++count + ": File " + event.context() + " is changed!"); break; case "ENTRY_CREATE": System.out.println(++count + ": File " + event.context() + " is created!"); break; case "ENTRY_DELETE": System.out.println(++count + ": File " + event.context() + " is deleted!"); break; default: System.out.println(++count + ": UNKNOWN EVENT!"); } } key.reset(); } } }

Cuando ejecuté esto y luego abrí el Notepad ++ y luego creé un nuevo archivo vacío y lo a.txt como a.txt en el directorio C:/tmp/ obtuve el resultado:

1: File a.txt is created! 2: File a.txt is deleted! 3: File a.txt is created!

¿Porqué es eso? Parece que el archivo fue creado y luego eliminado y luego creado de nuevo. ¿Por qué?

Cuando puse algo de texto en el archivo y lo guardé, el resultado fue:

4: File a.txt is changed! 5: File a.txt is changed!

¿Por qué cambió dos veces?


Creé una pequeña biblioteca de la utilidad FileWatcher: https://github.com/finsterwalder/fileutils

Permite establecer un período de gracia. Se acumulan múltiples eventos dentro del período de gracia y solo se activan una vez.

No debe usar Notepad ++ para sus experimentos, ya que no sabe qué está haciendo Notepad ++. Puede ser que Notepad ++ esté escribiendo en un archivo varias veces. O podría escribir un archivo con un nombre diferente y cambiarle el nombre, cuando haya terminado o lo que sea. Escribe tu propio código para manipular archivos y mira eso.


El evento Modificar del Service Watch genera dos eventos. Cuando modificamos un archivo ya existente, el sistema de archivos primero lo crea con 0 bytes y dispara un evento de modificación y luego escribe datos en él. Luego se dispara el evento modificar nuevamente. Es por eso que mostraba dos eventos de modificación. Entonces, lo que he hecho para resolver este problema, solo uso el contador para verificar que mi tarea debería activarse solo una vez

Path path = null; int count = 0; try { path = Paths.get(new Utility().getConfDirPath()); System.out.println("Path: " + path); } catch (UnsupportedEncodingException e1) { e1.printStackTrace(); } WatchService watchService = null; try { watchService = FileSystems.getDefault().newWatchService(); path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY,StandardWatchEventKinds.ENTRY_DELETE); } catch (IOException ioe) { ioe.printStackTrace(); } while(true) { WatchKey key = null; try { key = watchService.take(); } catch(InterruptedException ie) { ie.printStackTrace(); } for(WatchEvent<?> event: key.pollEvents()) { switch(event.kind().name()) { case "ENTRY_MODIFY": System.out.println(++count + ": File " + event.context() + " is changed!"); if (count%2==0) { doOnChange(); // do whatever you want } break; case "ENTRY_DELETE": System.out.println(++count + ": File " + event.context() + " is deleted!"); break; default: System.out.println(++count + ": UNKNOWN EVENT!"); } } // reset the key boolean valid = key.reset(); if (!valid) { System.out.println("Key has been unregistered"); } }


Los eventos de creación y eliminación de archivos funcionan correctamente en mi sistema (Windows 7 + 1.7.0_21).

El mensaje de evento de cambio se muestra la cantidad de tiempo (n) para cada operación de Ctrl + s en ese archivo.

// Removed the "//" after director name as D://tmp" //Added just to see the message with a 1 ms gap. Thread.sleep(1000); // after key.reset();

Ejemplo: Si abrimos el archivo y seguimos presionando las teclas crtl + s (guardar sin cambios / con cambios). El siguiente mensaje se mostrará (repetidamente) para cada operación de guardado.

File YourFileName.txt is changed!

El motivo está en las ventanas. El WatchService está comparando los cambios del archivo con la marca de tiempo en lugar de la suma de comprobación.

Más descripción dada aquí Dependencias de la plataforma


esto funciona para mi

// get the first event before looping WatchKey key = this.watcher.take(); // reset key (executed twice but not invoke the polled events) while (key != null && key.reset() ) { // polled events for (final WatchEvent<?> event : key.pollEvents()) { System.out.printf("/nGlobal received: %s, event for file: %s/n", event.kind(), event.context()); switch (event.kind().name()) { case "ENTRY_CREATE": LOGGER.debug("event ENTRY_CREATE"); break; case "ENTRY_DELETE": LOGGER.debug("event ENTRY_DELETE"); break; case "ENTRY_MODIFY": LOGGER.debug("event ENTRY_MODIFY"); break; default: LOGGER.debug("event other [OVERFLOW]"); break; } } key = this.watcher.take(); }