2013-04-21 3 views
23
import java.io.*; 
import java.nio.file.*; 

public class Tmp { 

    public static void main(String [] args) throws IOException { 
     int count = 0; 
     Path path = Paths.get("C:\\tmp\\"); 
     WatchService ws = null; 
     try { 
      ws = FileSystems.getDefault().newWatchService(); 
      path.register(ws, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, 
        StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.OVERFLOW); 
     } catch (IOException ioe) { 
      ioe.printStackTrace(); 
     } 

     while(true) { 
      WatchKey key = null; 
      try { 
       key = ws.take(); 
      } catch(InterruptedException ie) { 
       ie.printStackTrace(); 
      } 

      for(WatchEvent<?> event: key.pollEvents()) { 
       switch(event.kind().name()) { 
        case "OVERFLOW": 
         System.out.println(++count + ": OVERFLOW"); 
         break; 
        case "ENTRY_MODIFY": 
         System.out.println(++count + ": File " + event.context() + " is changed!"); 
         break; 
        case "ENTRY_CREATE": 
         System.out.println(++count + ": File " + event.context() + " is created!"); 
         break; 
        case "ENTRY_DELETE": 
         System.out.println(++count + ": File " + event.context() + " is deleted!"); 
         break; 
        default: 
         System.out.println(++count + ": UNKNOWN EVENT!"); 
       } 
      } 

      key.reset(); 
     }  
    } 
} 

Когда я запускаю это, а затем открыл Notepad ++, а затем создал новый пустой файл и сохранил его как a.txt в каталоге C:\tmp\ я получил результат:Почему WatchService генерирует так много операций?

1: File a.txt is created! 
2: File a.txt is deleted! 
3: File a.txt is created! 

Почему? Похоже, что файл был создан, а затем удален, а затем снова создан. Зачем?

Когда я положил текст в файл и сохраняется его выход был:

4: File a.txt is changed! 
5: File a.txt is changed! 

Почему это изменить дважды?

+5

Я думаю, что поведение, которое вы видите с помощью WatchService, связано с тем, как Notepad ++ и в некоторой степени работает, как работает операционная система Windows при выполнении операций ввода-вывода. Я обнаружил, что что-то вроде «стандартного» блокнота Windows обычно производит наиболее ожидаемое поведение. Я подозреваю, что если вы используете Process Explorer (http://technet.microsoft.com/en-gb/sysinternals/bb896653.aspx) для мониторинга активности ввода-вывода на уровне ОС вы увидите те же результаты. –

+2

Это может быть связано с тем, что записи контента и метаданных выполняются отдельно. – afk5min

ответ

0

События создания и удаления файлов корректно работают в моей системе (Window 7 + 1.7.0_21).

Сообщение о событии изменения отображается количество времени в (п) для каждого Ctrl +сек работы на этом файле.

 // Removed the "//" after director name as D://tmp" 
     //Added just to see the message with a 1 ms gap. 
     Thread.sleep(1000); // after key.reset(); 

Пример: Если мы открываем файл и сохранить на нажатие Ctrl + С (за исключением без каких-либо изменений/с изменениями). Следующее сообщение будет отображаться (повторно) для каждой операции сохранения.

 File YourFileName.txt is changed! 

Причина в Windows: WatchService сравнивает изменения файлов с меткой времени вместо контрольной суммы.

Больше описание дано здесь Platform dependencies

+0

Это не разрыв в 1 миллисекунду, это промежуток в 1 секунду. Конечно, вы не увидите эффекта, если вы ждете очень долгое время в компьютерных терминах, прежде чем снова проверить. Что касается этого: «Причина в Windows, WatchService сравнивает изменения файлов с меткой времени вместо контрольной суммы». э-э ... что? –

+0

@RobinGreen, скажите, пожалуйста, каково ваше исключение и ваш ответ. – VKPRO

0

это работает для меня

// get the first event before looping 
    WatchKey key = this.watcher.take(); 

    // reset key (executed twice but not invoke the polled events) 
    while (key != null && key.reset()) { 
     // polled events 
     for (final WatchEvent<?> event : key.pollEvents()) { 
     System.out.printf("\nGlobal received: %s, event for file: %s\n", event.kind(), 
      event.context()); 

     switch (event.kind().name()) { 
     case "ENTRY_CREATE": 
      LOGGER.debug("event ENTRY_CREATE"); 
      break; 
     case "ENTRY_DELETE": 
      LOGGER.debug("event ENTRY_DELETE"); 
      break; 
     case "ENTRY_MODIFY": 
      LOGGER.debug("event ENTRY_MODIFY"); 
      break; 
     default: 
      LOGGER.debug("event other [OVERFLOW]"); 
      break; 
     } 
     } 

     key = this.watcher.take(); 
    } 
1

Изменить событие Watch Service генерирует два события. Когда мы модифицируем уже существующий файл, файловая система сначала создает его с 0 байтами и запускает событие изменения, а затем записывает на него данные. Затем он снова запускает событие изменения. Вот почему он показывал два события изменения. Так что я сделал, чтобы решить эту проблему, я просто использовать счетчик, чтобы проверить свою задачу должен быть запущен только один раз даже сосчитать

 Path path = null; 
     int count = 0; 

     try { 
      path = Paths.get(new Utility().getConfDirPath()); 
      System.out.println("Path: " + path); 
     } catch (UnsupportedEncodingException e1) { 
      e1.printStackTrace(); 
     } 

     WatchService watchService = null; 
     try { 
      watchService = FileSystems.getDefault().newWatchService(); 
      path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY,StandardWatchEventKinds.ENTRY_DELETE); 
     } catch (IOException ioe) { 
      ioe.printStackTrace(); 
     } 


     while(true) { 
      WatchKey key = null; 
      try { 
       key = watchService.take(); 
      } catch(InterruptedException ie) { 
       ie.printStackTrace(); 
      } 

      for(WatchEvent<?> event: key.pollEvents()) { 
       switch(event.kind().name()) { 
        case "ENTRY_MODIFY": 
         System.out.println(++count + ": File " + event.context() + " is changed!"); 

         if (count%2==0) { 
          doOnChange(); // do whatever you want 
         } 
         break; 
        case "ENTRY_DELETE": 
         System.out.println(++count + ": File " + event.context() + " is deleted!"); 
         break; 
        default: 
         System.out.println(++count + ": UNKNOWN EVENT!"); 
       } 
      } 

      // reset the key 
      boolean valid = key.reset(); 
      if (!valid) { 
       System.out.println("Key has been unregistered"); 
      } 

     }  
0

Я создал небольшой FileWatcher Utility Library: https://github.com/finsterwalder/fileutils

Это позволяет установить льготный период. Несколько событий внутри льготного периода накапливаются и запускаются только один раз.

Вы не должны использовать Notepad ++ для своих экспериментов, так как вы не знаете, что делает Notepad ++. Возможно, Notepad ++ на самом деле пишет файл несколько раз. Или он может написать файл с другим именем и переименовать его, когда это будет сделано или что-то еще. Создайте свой собственный код, чтобы манипулировать файлами и смотреть его.