2015-09-21 5 views
2

Я играл с java.nio.file.WatchService и заметил, что Path s вернулся с WatchEvent.context() не вернул правильное значение .toAbsolutePath(). Ниже приведен пример применения:WatchService - неверно разрешенный абсолютный путь

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?

ответ

3

Это не ошибка, но, безусловно, сбивает с толку.

Если WatchEvent.context() возвращает Path то относительно:

В случае ENTRY_CREATE, ENTRY_DELETE и ENTRY_MODIFY МЕРОПРИЯТИЙ контекста является путем, который относительный путь между директорией зарегистрированном с часами служба и созданная запись, удалены или изменены.

Теперь, если вы включите такой путь в абсолютный путь, вызвав toAbsolutePath(), это происходит не по отношению к просмотренному каталогу, а к каталогу по умолчанию.

Этот метод решает путь в реализации зависимым образом, обычно путем разрешения путь против каталога файловой системы по умолчанию. В зависимости от реализации этот метод может вызвать ошибку ввода-вывода , если файловая система недоступна.

Поэтому, чтобы превратить путь в абсолютный путь, который вы должны использовать

watchedDirectory.resolve(createdFile); 
+2

Если, как я, вы смешивание просмотрели каталоги в одном цикле обработки событий (и, таким образом, рискуют иметь несколько файлов одно и то же имя в разных каталогах, полезно иметь возможность получить каталог, который оценивается текущим ключом: '((Path) key.watchable()). resolve (((WatchEvent )) .context()) ' – Guus