Notez comment utiliser WatchService pour surveiller les changements de dossier et de fichier dans Java.
OS Window 10
Java
java version "1.8.0_151"
Java(TM) SE Runtime Environment (build 1.8.0_151-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.151-b12, mixed mode)
Hello World
package sample.watch;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Paths;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.nio.file.Watchable;
import static java.nio.file.StandardWatchEventKinds.*;
import static java.nio.file.WatchEvent.*;
public class Main {
public static void main(String[] args) {
WatchService watcher;
try {
watcher = FileSystems.getDefault().newWatchService();
Watchable path = Paths.get("./build");
path.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
} catch (IOException e) {
e.printStackTrace();
return;
}
while (true) {
WatchKey watchKey;
try {
watchKey = watcher.take();
} catch (InterruptedException e) {
System.err.println(e.getMessage());
return;
}
for (WatchEvent<?> event : watchKey.pollEvents()) {
Kind<?> kind = event.kind();
Object context = event.context();
System.out.println("kind=" + kind + ", context=" + context);
}
if (!watchKey.reset()) {
System.out.println("WatchKey est désactivé");
return;
}
}
}
}
** Résultat d'exécution **

La description
WatchService watcher;
try {
watcher = FileSystems.getDefault().newWatchService();
...
} catch (IOException e) {
e.printStackTrace();
return;
}
WatchService avec FileSystems.getDefault (). NewWatchService ()import static java.nio.file.StandardWatchEventKinds.*;
...
Watchable path = Paths.get("./build");
path.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
Path hérite de Watchable, il peut donc être utilisé comme cible de surveillance.
--Spécifiez l'événement que vous souhaitez surveiller après le deuxième argument
--Spécifiez les constantes définies dans StandardWatchEventKinds
--Cependant, ʻOVERFLOW` n'a pas besoin d'être spécifié (les détails seront décrits plus tard). while (true) {
WatchKey watchKey;
try {
watchKey = watcher.take();
} catch (InterruptedException e) {
System.err.println(e.getMessage());
return;
}
...
}
--Lorsque vous exécutez la méthode take () de WatchService, il attend le traitement jusqu'à ce que l'événement à surveiller se produise.
--Un objet WatchKey est renvoyé lorsqu'un événement surveillé se produit
--WatchKey est un objet qui est créé lorsque vous enregistrez une cible de surveillance avec register () ʻof Watchable`, et vous pouvez contrôler l'état de la surveillance comme le référencement des informations d'événement qui se sont produites pour chaque cible de surveillance et l'annulation de la surveillance. ça peut
for (WatchEvent<?> event : watchKey.pollEvents()) {
Kind<?> kind = event.kind();
Object context = event.context();
System.out.println("kind=" + kind + ", context=" + context);
}
WatchEvent) avec pollEvents () ʻof WatchKey`.WatchEvent
--kind: Type d'événement survenu
--context: objet Path avec un chemin relatif vers l'entrée créée / modifiée / supprimée (fichier ou dossier)
--count: nombre de fois où ce type d'événement s'est produit if (!watchKey.reset()) {
System.out.println("WatchKey est désactivé");
return;
}
--Enfin, exécutez reset () de WatchKey
――Pourquoi vous devez appeler reset () sera expliqué plus tard.
reset () est boolean, qui vous indique si WatchKey est toujours valide.
--Si false, la WatchKey est désactivée et la surveillance ne peut pas continuer.WatchKey.cancel ()WatchService.close () a annulé la surveillance de WatchService--WatchKey a deux états, "READY" et "SIGNALLED".
--Lorsqu'il est généré par Watchable.register (), il est à l'état READY.
SIGNALLED lorsqu'un événement est détecté
--Lorsque vous exécutez WatchKey.reset (), il revient à l'état READY.

--WatchService stocke la WatchKey créée lorsque vous avez exécuté Watchable.register ()
WatchKey dont le statut est SIGNALLED.
--La WatchKey immédiatement après sa création est dans l'état READY, donc elle n'est pas dans la file d'attente.WatchKey dont le statut est SIGNALLED est ajoutée à la file d'attente de WatchService.WatchService peuvent récupérer WatchKey au début de la file d'attente en utilisant les méthodesWatchService.take ()oupoll ()(supprimées de la file d'attente). Ru)
--take () bloque le traitement lorsque la file d'attente est vide et attend que WatchKey soit ajouté à la file d'attente
--poll () retourne null sans blocage si la file d'attente est vide
--Pour poll (), vous pouvez spécifier le délai d'expiration comme argument et le laisser attendre jusque-là.
--La WatchKey sortie de la file d'attente avec take () ʻou poll ()` ne sera pas remise en file d'attente telle quelle.WatchKey supprimé de la file d'attente est toujours SIGNALLEDWatchKey
--WatchKey est sécurisé pour les threads, donc même si des informations d'événement sont ajoutées pendant le traitement de l'événement, l'état interne ne sera pas corrompu.
--pollEvents () retourne une copie des informations d'événement que WatchKey avait à ce moment-là.pollEvents () ont été supprimées de l'intérieur de WatchKey.
--En bref
--Une fois retiré de la file d'attente, WatchKey ne sera plus mis en file d'attente s'il n'est pas touché.
--Si vous n'êtes pas dans la file d'attente, vous ne pouvez pas le récupérer avec take () ou poll ()
Cela signifie
--L'état doit être retourné à «READY» pour que «WatchKey» soit à nouveau mis en file d'attente.WatchKey sont vides (pas d'événements non traités), le statut revient à READY.SIGNALLED.Résumé,
--La WatchKey immédiatement après la création est dans l'état READY.
--Si un événement est détecté et changé en SIGNALLED, il sera ajouté à la file d'attente dans WatchService.
WatchKey de la file d'attente avec take (), poll ()
--Une fois qu'une WatchKey est hors de la file d'attente, elle ne retournera pas dans la file d'attente sans autorisation à moins que vous n'exécutiez reset ().
--S'il y a des événements non traités, ils peuvent être mis en file d'attente en tant que SIGNALLED
S'il n'y a aucun événement non traité, il sera à l'état READY, et la prochaine fois que l'événement surveillé se produira, il sera à nouveau SENGALLED et sera mis en file d'attente.package sample.watch;
...
public class Main {
public static void main(String[] args) {
...
while (true) {
WatchKey watchKey;
try {
watchKey = watcher.take();
Thread.sleep(1000);★ Ajout
} catch (InterruptedException e) {
...
}
...
}
}
}
** Résultat d'exécution **

La description
--Si un événement est perdu ou détruit pour une raison quelconque, un événement spécial appelé «OVERFLOW» est utilisé.
--Par exemple, selon l'environnement d'exécution, il peut y avoir une limite sur le nombre d'événements stockés dans WatchKey, et si un événement qui dépasse cette limite se produit, l'événement ʻOVERFLOW sera utilisé. --Dans l'exemple ci-dessus, attendez 1 seconde avant d'obtenir l'événement (pollEvents ()), enregistrez tous les événements d'un grand nombre de générations de fichiers dans WatchKey, et générez de force ʻOVERFLOW. Est
est notifié lorsque la condition est remplie même si elle n'est pas spécifiée comme événement surveillé dans l'enregistrement avecWatchable.register ()`.package sample.watch;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Paths;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.nio.file.Watchable;
import static java.nio.file.StandardWatchEventKinds.*;
import static java.nio.file.WatchEvent.*;
public class Main {
public static void main(String[] args) {
WatchService watcher;
WatchKey fooKey;
WatchKey barKey;
try {
watcher = FileSystems.getDefault().newWatchService();
Watchable foo = Paths.get("./build/foo");
fooKey = foo.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
Watchable bar = Paths.get("./build/bar");
barKey = bar.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
} catch (IOException e) {
e.printStackTrace();
return;
}
while (true) {
WatchKey watchKey;
try {
watchKey = watcher.take();
} catch (InterruptedException e) {
System.err.println(e.getMessage());
return;
}
for (WatchEvent<?> event : watchKey.pollEvents()) {
Kind<?> kind = event.kind();
if (kind == OVERFLOW) {
continue;
}
Object context = event.context();
String directory;
if (watchKey == fooKey) {
directory = "foo";
} else if (watchKey == barKey) {
directory = "bar";
} else {
directory = "unknown";
}
System.out.println("directory=" + directory + ", kind=" + kind + ", context=" + context);
}
if (!watchKey.reset()) {
System.out.println("WatchKey est désactivé");
return;
}
}
}
}
** Résultat d'exécution **

La description
--Un WatchService peut surveiller plusieurs dossiers
WatchKey obtenue parWatchService.take (). --Si vous enregistrez laWatchKey qui est retournée comme valeur de retour de Watchable.register ()`, vous pouvez la comparer pour identifier dans quel dossier se trouve l'événement.Recommended Posts