WatchService - 错误解析绝对路径

时间:2015-09-21 09:10:32

标签: java nio watchservice java.nio.file

我一直在玩java.nio.file.WatchService并注意到Path返回的WatchEvent.context()未返回正确的.toAbsolutePath()。这是一个示例应用程序:

public class FsWatcher {
  public static void main(String[] args) throws IOException, InterruptedException {
    if (args.length != 1) {
      System.err.println("Invalid number of arguments: " + args.length);
      return;
    }
    //Run the application with absolute path like /home/<username>
    final Path watchedDirectory = Paths.get(args[0]).toAbsolutePath();
    final FileSystem fileSystem = FileSystems.getDefault();
    final WatchService watchService = fileSystem.newWatchService();
    watchedDirectory.register(watchService, StandardWatchEventKinds.ENTRY_CREATE);

    while (true) {
      WatchKey watchKey = watchService.take();
      for (WatchEvent<?> watchEvent : watchKey.pollEvents()) {
        if (watchEvent.kind().equals(StandardWatchEventKinds.OVERFLOW)) {
          continue;
        }

        final Path createdFile = (Path) watchEvent.context();
        final Path expectedAbsolutePath = watchedDirectory.resolve(createdFile);
        System.out.println("Context path: " + createdFile);
        System.out.println("Context absolute path: " + createdFile.toAbsolutePath());
        System.out.println("Expected absolute path: " + expectedAbsolutePath);
        System.out.println("usr.dir: " + System.getProperty("user.dir"));
      }
      watchKey.reset();
    }
  }
}

示例输出:

Context path: document.txt
Context absolute path: /home/svetlin/workspaces/default/FsWatcher/document.txt
Expected absolute path: /home/svetlin/document.txt
usr.dir: /home/svetlin/workspaces/default/FsWatcher

似乎绝对路径是针对user.dir系统属性而不是用于Path注册的WatchService解析的。这是一个问题,因为当我尝试使用(例如Files.copy())从WatchEvent返回的路径时,我收到java.nio.file.NoSuchFileException,这是预期的,因为此路径中没有此类文件。我错过了什么或这是JRE中的错误吗?

1 个答案:

答案 0 :(得分:8)

这不是一个错误,但肯定令人困惑。

如果WatchEvent.context()返回Path,那么它是相对的:

  

在ENTRY_CREATE,ENTRY_DELETE和ENTRY_MODIFY事件的情况下   context是一个Path,它是目录之间的相对路径   在监视服务中注册,以及创建的条目,   删除或修改。

现在,如果通过调用toAbsolutePath()将这样的路径转换为绝对路径,则这与发出的目录无关,而是与默认目录相关。

  

此方法以依赖于实现的方式解析路径,   通常通过针对文件系统默认解析路径   目录。根据实现,此方法可能会抛出一个   如果无法访问文件系统,则会出现I / O错误。

因此,要将路径转换为绝对路径,您需要使用

watchedDirectory.resolve(createdFile);