我正在尝试使用Java SE 7中提供的WatchService来监视远程目录(在网络机器上)。当我在Windows XP上运行这个程序时,它工作得很好,但在Windows 7上,WatchService.take()不等待,返回一个无效的密钥。
下面是示例代码:import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.nio.file.WatchEvent.Kind;
public class MyWatchingService {
public void watchDir(Path path) throws IOException, InterruptedException {
try (WatchService watchService = FileSystems.getDefault().newWatchService()) {
path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE);
while (true) {
// gets a watch key
final WatchKey key = watchService.take();
// retrieves pending events for a key.
for (WatchEvent<?> watchEvent : key.pollEvents()) {
// retrieves the event type and count.
// gets the kind of event (create, delete)
final Kind<?> kind = watchEvent.kind();
// handles OVERFLOW event
if (kind == StandardWatchEventKinds.OVERFLOW) {
continue;
}
final WatchEvent<Path> watchEventPath = cast(watchEvent);
final Path entry = watchEventPath.context();
// outputs an event type and entry
System.out.println(kind + " -> " + entry);
}
boolean valid = key.reset();
//exit loop if the key is not valid
if (!valid) {
System.out.println("Key is invalid!");
break;
}
}
}
}
public void writeFile (Path path, String fileName) throws IOException {
Path target = Paths.get(path.toString(), fileName);
if (target.toFile().exists()) {
Files.delete(target);
System.out.println("file is deleted ok!");
}
Path fileTo = Files.createFile(target);
Files.write(fileTo, String.valueOf(true).getBytes(), StandardOpenOption.WRITE);
System.out.println("file is written ok!");
}
@SuppressWarnings("unchecked")
private static <T> WatchEvent<T> cast(WatchEvent<?> event) {
return (WatchEvent<T>)event;
}
/**
* @param args
*/
public static void main(String[] args) {
// case 1: network directory mapped to Y volume
final Path path = Paths.get("Y:/workspace");
// case 2: local directory:
// final Path path = Paths.get("D:/workspace");
MyWatchingService service = new MyWatchingService();
try {
long start = System.currentTimeMillis();
service.watchDir(path);
System.out.println("exiting after " + Long.toString(System.currentTimeMillis() - start) + "ms...");
service.writeFile(path, "test");
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
输出如下:
Key is invalid!
exiting after 16ms...
file is deleted ok!
file is written ok!
你可以看到,我检查了我是否可以在这个网络目录下写/删除文件。我也尝试过没有映射定义路径像这样://server/workspace
,没有运气。如果我在本地目录下对注释掉的情况2运行相同的程序,那么它将进入等待状态,没有预期的输出。
我使用jdk1.7.0_17, 64位。(我尝试了jre7, 32位,但也没有运气)。远程目录位于Windows Server 2008 R2 Standard.
我在API中读到下面的句子,这让我怀疑这根本不可能:
如果一个被监视的文件不在本地存储设备上,那么它就在如果可以检测到对文件的更改,则特定于实现。在特别是,它不要求对文件进行更改远程系统被检测。
这对我来说是个坏消息,因为我在使用WatchService的这个策略上投入了大量时间。有人有什么想法/经验,为什么它不能在Windows 7上工作,或者它是可能的吗?如果没有,有什么替代方法呢?
正如文档所说:我根本不希望'watching'在网络驱动器上工作。
它是否工作当然取决于客户端的操作系统,也许它的配置和在服务器的操作系统,也许它的配置,加上一些其他未知因素;似乎非常脆弱,不值得指望。
文档中也提到了一个简单的替代方法:
[…或使用原始机制,如轮询,当本机设施不可用时
轮询方法可以在纯Java中实现,根本不需要使用NIO
。警告:可能导致资源(网络)大量使用。
和往常一样,建议你退一步,重新考虑一下你是否真的需要在这些文件系统操作上构建你的"网络协议",或者你是否可以用另一种方式实现你想要/需要的