如何获得 WatchService 中的真实路径

How can I get the real path in WatchService

在java中,当我添加或更改或删除任何文件时,我希望程序在另一个directory.It中执行相同的操作意味着,如果我在"test.txt"中添加一个文件E://aaa,程序应该从E://aaa复制"test.txt"到D://bbb。

我使用java.nio.file.WatchService来实现它,但是我无法在程序中获取文件的真实路径,这是我的代码:

public void watchPath(Path watchPath, Path targetPath) throws IOException, InterruptedException {
    try (WatchService watchService = FileSystems.getDefault().newWatchService()) {
        watchPath.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_MODIFY,
                StandardWatchEventKinds.ENTRY_DELETE);
        while (true) {
            final WatchKey key = watchService.take();
            for (WatchEvent<?> watchEvent : key.pollEvents()) {
                final Kind<?> kind = watchEvent.kind();
                if (kind == StandardWatchEventKinds.OVERFLOW) {
                    continue;
                }
                final WatchEvent<Path> watchEventPath = (WatchEvent<Path>) watchEvent;
                Path systemFileDir = (Path) key.watchable(); // TODO Here can not get the real path
                //System.out.println(systemFileDir.toString()); // E:/aaa
                //System.out.println(systemFileDir.toAbsolutePath()); // E:/aaa
                //System.out.println(systemFileDir.toRealPath()); // E:/aaa
                final Path path = watchEventPath.context();
                String fileAbsPath = systemFileDir + File.separator + path;
                Path original = Paths.get(fileAbsPath);
                String targetAbsPath = fileAbsPath.replace(watchPath.toString(), targetPath.toString());
                Path target = Paths.get(targetAbsPath);
                File file = new File(targetAbsPath);
                if (kind == StandardWatchEventKinds.ENTRY_CREATE || kind == StandardWatchEventKinds.ENTRY_MODIFY) {
                    if (file.isDirectory() && !file.exists()) { // 如果是目录
                        file.mkdirs();
                    } else {
                        Files.copy(original, target, StandardCopyOption.REPLACE_EXISTING);
                    }
                }
                if (kind == StandardWatchEventKinds.ENTRY_DELETE) {
                    Files.delete(target);
                }
            }
            boolean valid = key.reset();
            if (!valid) {
                break;
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

现在的问题是,当我在E://aaa/x中添加文件或目录时,程序无法获取真实路径。比如我添加了文件E://aaa/x/test.txt,我希望能得到这个绝对路径然后复制到destination,但是我得到的只是RootPath E://aaa。

我该如何解决?谢谢!

根据您的评论:

您遇到问题的原因是您只注册了父文件夹。如果您想获得在子文件夹中所做编辑的确切路径,那么您还需要在这些子文件夹中注册您的观察者。一种方法是 walk through the entire file tree 一开始就注册所有内容。

这是一个完美的例子:

http://docs.oracle.com/javase/tutorial/displayCode.html?code=http://docs.oracle.com/javase/tutorial/essential/io/examples/WatchDir.java

现在您只需修改该代码片段以满足您的需要,方法是调整 processEvents() 方法来检查事件类型,然后使用 child 变量在您的其他文件夹中执行相同的操作.

这是您可以对 processEvents 进行编辑以在镜像目录中添加文件夹的粗略示例:

    Path child = dir.resolve(name);
    if (kind == StandardWatchEventKinds.ENTRY_CREATE && (check if directory here))
    {
        String destinationToMirror = "D" + child.toString().substring(1);
        File file = new File(destinationToMirror);
        file.mkdir();
    }

否则请继续阅读遍历文件树,这样您就可以将必要的位添加到您自己的代码中: http://docs.oracle.com/javase/tutorial/essential/io/walk.html


原答案:

试试这样:

Path original = systemFileDir.resolve(watchEventPath.context());

而不是:

final Path path = watchEventPath.context();
String fileAbsPath = systemFileDir + File.separator + path;
Path original = Paths.get(fileAbsPath);

请注意主要区别在于如何使用 dir.resolve

解析路径

来源:java.nio.file.WatchEvent gives me only relative path. How can I get the absolute path of the modified file?