Java nio的WatchService用于多个目录

10

我想使用Java NIO的WatchService监视多个目录。 我的问题是要监视的目录数量是动态的,用户可以向WatchService添加任意数量的目录。这是否可行?


2
是的,这是可以实现的。 - Sanchit
@Sanchit 感谢你的回答。你能指导我如何实现这个吗? - G.S
4个回答

12

可以使用相同的WatchService来注册多个路径。每个路径都有自己的WatchKey。然后,take()poll()将返回对应于被修改的路径的WatchKey

请参见Java的WatchDir示例以获取详细信息。


4

按照之前的答案,可以使用以下链接:Oracle WatchDir

您可以先创建WatchService

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

此时,您可以将许多路径添加到同一个 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);

接下来你可以按照以下方式管理事件:

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();
}

现在,如果您想获取有关事件发生地的更多信息,您可以创建一个地图,通过示例将键和路径链接起来(您可以考虑根据需要创建变量作为类级别):
Map<WatchKey, Path> keys;

在这个例子中,您可以将路径放在列表中,然后需要循环遍历并将每个路径添加到同一个WatchService中:
for (Path path : paths) {
    WatchKey key = path.register(
            watchService,
            StandardWatchEventKinds.ENTRY_CREATE);
    keys.put(key, path);
}

现在,要管理这些事件,您可以添加类似以下内容的代码:
WatchKey key;
while ((key = watchService.take()) != null) {
    Path path = keys.get(key);
    // More code here.
    key.reset();
}

2
我会尽力解释如何使用WatchService来完成这个任务。以下是一段代码示例,说明如何使用一个WatchService实例监听两个路径:

我只是试图解释如何使用WatchService来精确完成此操作。

以下是一段代码,演示如何使用一个WatchService实例并监听两个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);

示例基于Oracle示例

0

为几个固定目录添加一个完整的简单解决方案。此示例有3个将被监视的目录,当创建我正在寻找的文件时,我将对其进行处理。在Linux中使用这种方法而不是需要root访问权限的端口监听器。

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();
        }
    }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接