为什么WatchService会产生如此多的操作?

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 ++然后创建一个新的空文件并将其保存为C:\tmp\目录中的a.txt我得到了输出:

 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! 

为什么会改变两次?

Watch Service的Modify事件生成两个事件。 当我们修改现有文件时,文件系统首先用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"); } } 

这对我有用

  // 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(); } 

我创建了一个小的FileWatcher实用程序库: https : //github.com/finsterwalder/fileutils

它允许设置宽限期。 宽限期内的多个事件被累积并仅触发一次。

您不应该使用Notepad ++进行实验,因为您不知道Notepad ++正在做什么。 可能是,Notepad ++实际上是多次写入文件。 或者它可以写一个具有不同名称的文件并重命名,完成后或诸如此类的东西。 编写自己的代码来操作文件并观察它。

文件创建和删除事件在我的系统中正常工作(Window 7 + 1.7.0_21)。

更改事件消息显示该文件上每个Ctrl + s操作的时间(n)。

  // 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(); 

示例:如果我们打开文件并继续按下crtl + s(保存没有任何更改/更改)。 对于每个保存操作,将显示(重复)以下消息。

  File YourFileName.txt is changed! 

原因是在Windows中,WatchService将文件更改与时间戳而不是校验和进行比较。

此处给出的更多描述平台依赖性