Java NIO WatchService

У меня есть проект Java, в котором нам нужно продолжать прослушивать какой-то путь, чтобы определить, есть ли какой-либо новый файл XML, и если это правда, нам нужно обработать его с помощью нескольких других правил.

WatchService очень хорошо справляется, чтобы обнаружить, есть ли у меня новый файл для обработки, но я не смог управлять им, чтобы я мог прочитать файл, я просто возвращаю мне имя файла из события.

Есть ли способ сделать это с WatchService? Если нет, то какой другой sugestion достичь?

Спасибо.


person Victor    schedule 03.09.2020    source источник
comment
Если у вас есть имя файла, вы не можете просто открыть файл?   -  person markspace    schedule 04.09.2020
comment
Если просто под именем файла вы подразумеваете результат WatchEvent#context(), затем просто сопоставьте его с каталогом, чтобы получить полный путь.   -  person Slaw    schedule 04.09.2020


Ответы (1)


Конечно, вы можете легко сделать это:

  1. Создайте службу часов:

     WatchService watchService = null;
    
     try {
         watchService = FileSystems.getDefault().newWatchService();
         Path path = get(pathToSee);
         path.register(watchService, new WatchEvent.Kind[]{ENTRY_MODIFY, ENTRY_CREATE}, SensitivityWatchEventModifier.HIGH);
         watchEvent(watchService, path);
         log.info("Watch Service has ben created!");
     } catch (IOException e) {
         log.error("Exception has ben throw when the service have tried to createWatchService()", e);
     }
    

Примечание. Если у вас большое количество файлов для добавления, вы можете поставить:

SensitivityWatchEventModifier.HIGH

Для повышения чувствительности.

  1. Посмотрите, есть ли изменения в вашем каталоге:

     WatchKey key;
     while (true) {
         try {
             if ((key = watchService.take()) == null) break;
    
             for (WatchEvent<?> event : key.pollEvents()) {
                 log.info("Event kind:" + event.kind()
                         + ". File affected: " + event.context() + ".");
    
                 String fileName = event.context().toString();
                 File directory = path.toFile();
                 yourService.readContent(directory, fileName);
             }
             key.reset();
         } catch (InterruptedException | IOException e) {
             log.error("InterruptedException when try watchEvent()" + e);
         }
     }
    
  2. И, наконец, вы можете делать с этой информацией то, что хотите:

     try (BufferedReader br = new BufferedReader(new FileReader(directory + "/" + fileName))) {
         String strLine;
         while ((strLine = br.readLine()) != null) {
                 }
             }
         }
     }
    

Советы:

  1. Для этого вы можете создать отдельный поток или использовать Spring @Async для создания отдельного потока для обработки этой информации и увеличения параллелизма в вашем приложении.

  2. Вы также можете использовать Apache Commons для этого!

e.g:

public void getAll() throws Exception {
    FileAlterationObserver observer = new FileAlterationObserver(pathToSee);
    observer.addListener(new FileAlterationListenerAdaptor() {

        @SneakyThrows
        @Override
        public void onFileCreate(File file) {
            
            
        }

        @Override
        public void onFileDelete(File file) {
            
        }
    });
}
person Baptista    schedule 06.10.2020