[JAVA] Notes d'utilisation de WatchService

Notez comment utiliser WatchService pour surveiller les changements de dossier et de fichier dans Java.

environnement

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 **

watchservice.gif

La description

        WatchService watcher;
        try {
            watcher = FileSystems.getDefault().newWatchService();

            ...
        } catch (IOException e) {
            e.printStackTrace();
            return;
        }
import static java.nio.file.StandardWatchEventKinds.*;

...

            Watchable path = Paths.get("./build");
            path.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
        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);
            }
            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.

  1. Annulé explicitement avec WatchKey.cancel ()
  2. L'objet surveillé (répertoire, etc.) a été supprimé et est devenu inaccessible, et a été annulé implicitement.
  3. WatchService.close () a annulé la surveillance de WatchService

Changement d'état WatchKey

--WatchKey a deux états, "READY" et "SIGNALLED". --Lorsqu'il est généré par Watchable.register (), il est à l'état READY.

watchservice.png

Relation entre WatchService et WatchKey

watchservice.jpg

--WatchService stocke la WatchKey créée lorsque vous avez exécuté Watchable.register ()

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.

Événement OVERFLOW

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 **

watchservice.gif

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

Surveiller plusieurs dossiers

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 **

watchservice.gif

La description

--Un WatchService peut surveiller plusieurs dossiers

référence

Recommended Posts

Notes d'utilisation de WatchService
Notes d'utilisation de JavaParser
Mémo d'utilisation PlantUML
Notes d'utilisation de JUnit5
Notes d'utilisation de Spring Shell
Mémo d'utilisation de Spring Security CSRF
Spring Security Usage Memo Method Security
Mémo d'utilisation de Spring Security Remember-Me
Notes sur l'utilisation du plug-in de gestion des dépendances
Mémo d'utilisation de Spring Security CORS
Test de mémo d'utilisation de Spring Security
Authentification / autorisation de mémo d'utilisation de Spring Security
Mémo d'utilisation de JCA (Java Encryption Architecture)
En-tête de réponse de mémo d'utilisation de Spring Security
Gestion des sessions de mémo d'utilisation de Spring Security
Mémo d'utilisation de Spring Security Basic / mécanisme
Mémo entier
mémo docker
Spring Security Usage Memo Domain Object Security (ACL)
Mémo de Lombok
Mémo Dockerfile
Mémo Itérateur
mémo corretto
Mémo Java
Mémo AWS
Mémo Dcokerfile
utilisation d'irb
Memo Stream