问题
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();
}
}
}
When I run this and then opened the Notepad++ and then created a new empty file and saved it as a.txt
in the C:\tmp\
directory I got the output:
1: File a.txt is created!
2: File a.txt is deleted!
3: File a.txt is created!
Why is that? It looks like the file was created and then deleted and then created again. Why?
When I put some text in the file and saved it the output was:
4: File a.txt is changed!
5: File a.txt is changed!
Why did it change twice?
回答1:
Watch Service's Modify event generates two events. When we modify an already existing file, the file system first creates it with 0 bytes and fires a modify event and then writes data on it. Then it fires the modify event again. That's why It was showing two modify events. So What I have done to solve this problem, I just use counter to check my task should be triggered only once on even count
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");
}
}
回答2:
this works for me
// 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();
}
回答3:
I created a small FileWatcher Utility Library: https://github.com/finsterwalder/fileutils
It allows to set a grace period. Multiple events inside the grace period are accumulated and only triggered once.
You should not use Notepad++ for your experiments, since you don't know what Notepad++ is doing. It may be, that Notepad++ is actually writing to a file several times. Or it could write a file with a different name and rename it, when done or whatnot. Write your own code to manipulate files and watch that.
回答4:
The File creation and deletion events are working correctly in my system(Window 7 + 1.7.0_21).
The change event message is displayed number of time's(n) for each Ctrl+s operation on that file.
// 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();
Example : If we open the file and keep on pressing the crtl + s (save with out any changes/with changes). The following message will display(repeatedly) for each save operation.
File YourFileName.txt is changed!
Reason is in windows the WatchService is comparing the file changes with timestamp instead of checksum.
More description given here Platform dependencies
来源:https://stackoverflow.com/questions/16133590/why-does-watchservice-generate-so-many-operations