WatchService.take()在Windows-7-x64上不等待,同时观察远程目录中的更改

时间:2013-03-28 17:38:30

标签: java directory windows-7-x64 watchservice

我正在尝试使用Java SE 7中提供的WatchService来观察远程目录(在网络计算机上)。当我在Windows XP上运行程序时,它运行正常,但在Windows 7上,WatchService.take()没有&# 39;等待,返回无效密钥。

以下是示例代码:

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运行相同的程序,那么它将进入等待而没有按预期输出。

我使用64位的jdk1.7.0_17。 (我试过jre7,32位,但也没有运气)。远程目录位于Windows Server 2008 R2 Standard上。

我在API中读到了以下句子,这使我怀疑它根本不可能:

  

如果观看的文件不在本地存储设备上,那么它就是   特定实现,如果可以检测到对文件的更改。在   特别是,不需要对文件进行更改   检测远程系统。

这对我来说是个坏消息,因为我使用WatchService在这个策略上投入了大量时间。有人有任何想法/经验,为什么它不能在Windows 7上运行,或者它是否可能?如果没有,那将是另一种方法。

1 个答案:

答案 0 :(得分:2)

正如文档所说:我不希望“观看”在网络驱动器上工作

如果它确实起作用或者当然不取决于客户端的操作系统,也可能取决于服务器操作系统上的配置,可能还有其配置,以及其他一些未知因素;似乎非常脆弱,不值得依靠。

docs中也提到了一个简单的替代方案:

  

[...]或在本机设施不可用时使用原始机制,例如轮询

轮询方法可以在纯Java中实现,而根本不使用NIO。警告:结果可能是资源使用(网络)。

而且,与往常一样,建议稍稍退一步,重新考虑是否确实需要在这些文件系统操作上构建“网络协议”,或者如果您能够以其他方式实现您想要/需要的目标