Java nio WatchService for multiple directories
Asked Answered
D

4

11

I want to watch (monitor) multiple directories using Java NIO WatchService. My problem here is the number of directories to watch is dynamic and the user can add any number of directories to the WatchService. Is this achievable?

Dubrovnik answered 20/3, 2013 at 7:22 Comment(2)
Yes, it is achievable.Reynaud
@Reynaud Thanks for your answer. Can you please guide me how to achieve thisDubrovnik
A
12

It is possible to register multiple paths with the same WatchService. Each path gets its own WatchKey. The take() or poll() will then return the WatchKey corresponding to the path that was modified.

See Java's WatchDir example for details.

Astrodome answered 10/10, 2013 at 17:7 Comment(0)
C
4

Following the same link as in previous answers: Oracle WatchDir.

You can create first the WatchService:

WatchService watchService = FileSystems.getDefault().newWatchService();

At this point you can add many paths to the same WatchService:

Path path1 = Paths.get("full\path\1\\");
path1.register(watchService,
               StandardWatchEventKinds.ENTRY_CREATE);

Path path2 = Paths.get("full\path\2\\");
path2.register(watchService,
               StandardWatchEventKinds.ENTRY_CREATE);

Then you can manage the events as follow:

WatchKey key;
while ((key = watchService.take()) != null) {
    for (WatchEvent<?> event : key.pollEvents()) {
        System.out.println(
          "Event kind:" + event.kind() 
            + ". File affected: " + event.context() + ".");
    }
    key.reset();
}

Now, if you want to get more information about where was raised the event, you can create a map to link the key and the path by example (You can consider create the variable as class level following your needs):

Map<WatchKey, Path> keys;

In this example you can have the paths inside a list, then you need to loop into it and add each path to the same WatchService:

for (Path path : paths) {
    WatchKey key = path.register(
            watchService,
            StandardWatchEventKinds.ENTRY_CREATE);
    keys.put(key, path);
}

Now to manage the events, you can add something like it:

WatchKey key;
while ((key = watchService.take()) != null) {
    Path path = keys.get(key);
    // More code here.
    key.reset();
}
Came answered 6/2, 2020 at 18:46 Comment(0)
I
2

I am just trying to explain how exactly this can be done using WatchService.

Here is a piece of code that illustrates how you can use one WatchService instance and listen to two Paths

        this.watcher = FileSystems.getDefault().newWatchService();
        this.keys = new HashMap<>();

        Path plugins = Paths.get(INSTANCE.getPluginPath());
        logger.info(String.format("Scanning %s ...", plugins));
        registerAll(plugins);

        Path drivers = Paths.get(INSTANCE.getDriverPath());
        logger.info(String.format("Scanning %s ...", drivers));
        registerAll(drivers);

The example is based on Oracle Example

Innominate answered 1/2, 2017 at 8:33 Comment(0)
P
0

adding a complete simple solution for a few fixed directories. This example has 3 directories that will be monitored and when a file is created i am looking for, i will process it. Using this approach in Linux instead of a port listener which i need root access.

import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE;
import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;

import java.io.File;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.HashMap;
import java.util.Map;

public class WatchDirSimple {
    
    public static void main(String[] args) {
        try {
            
            WatchService watcher = FileSystems.getDefault().newWatchService();
            Map<WatchKey,Path> keys = new HashMap<WatchKey,Path>();
            
            WatchDirSimple watchDirSimple = new WatchDirSimple();
            
            WatchKey key;
            Path dir;
            
            dir = Paths.get(System.getProperty("user.home")+File.separator + "Documents\\PROD_Data\\ODBI");
            key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
            keys.put(key, dir);
            dir = Paths.get(System.getProperty("user.home")+File.separator + "Documents\\PROD_Data\\ODBI\\@fred");
            key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
            keys.put(key, dir);
            dir = Paths.get(System.getProperty("user.home")+File.separator + "Documents\\PROD_Data\\ODBI\\CMODupgrade");
            key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
            keys.put(key, dir);
            
            for (;;) {

                try {
                    key = watcher.take();
                } catch (InterruptedException x) {
                    return;
                }

                dir = keys.get(key);
                if (dir == null) {
                    System.err.println("WatchKey not recognized!!");
                    continue;
                }

                for (WatchEvent<?> event: key.pollEvents()) {
                    WatchEvent.Kind kind = event.kind();

                    // Context for directory entry event is the file name of entry
                    WatchEvent<Path> ev = (WatchEvent<Path>)event;
                    Path name = ev.context();
                    Path child = dir.resolve(name);

                    // print out event
                    System.out.format("%s: %s\n", event.kind().name(), child);
                }

                // reset key and remove from set if directory no longer accessible
                boolean valid = key.reset();
                if (!valid) {
                    keys.remove(key);

                    // all directories are inaccessible
                    if (keys.isEmpty()) {
                        break;
                    }
                }
            }

            watchDirSimple.register(dir, watcher, keys);
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
Platinumblond answered 11/3, 2021 at 20:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.