1

我正在尝试在客户端和服务器之间同步两个文件夹及其子目录。我有一个我在下面发布的这个类的修改版本。在我的 Client 类中,我创建了一个 WatchDir 对象并processEvents()在无限循环中调用它的方法。

如果事件已注册,则该方法返回一个myTuple对象(包含事件类型和路径对象的结构),否则返回 null。问题在于,这似乎只适用于目录中发生的第一个事件(即,如果我将文件添加到监视文件夹,我的 WatchDirobject.processEvents()返回一个带有ENTRY_CREATE事件的元组,并且永远不会返回另一个元组用于其他文件添加/删除/之后发生的修改)。我希望processEvents每次发生某些事件时都被连续调用(因此是无限的while)返回一个元组。

我修改后的 WatchDir:

import static java.nio.file.StandardWatchEventKinds.*;
import static java.nio.file.LinkOption.*;
import java.nio.file.attribute.*;
import java.io.*;
import java.util.*;
import java.util.concurrent.TimeUnit;

public class WatchDir {
    private final WatchService watcher;
    private final Map<WatchKey,Path> keys;
    private final boolean recursive;
    private boolean trace = false;

    public WatchDir(Path dir, boolean recursive) throws IOException {
        this.watcher = FileSystems.getDefault().newWatchService();
        this.keys = new HashMap<WatchKey,Path>(); //holds the key for each subdirectory
        this.recursive = true;

        registerAll(dir);
    }

    public void registerAll(Path start) throws IOException {
        Files.walkFileTree(start, new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
                register(dir);
                return FileVisitResult.CONTINUE;
            }
        });
    }

    public void register(Path dir) throws IOException {
        WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
        keys.put(key, dir);
    }

    public myTuple processEvents() {
        WatchKey key;
        //while (true) {

            try {
                key = watcher.take();
            } catch (InterruptedException e) {
                return new myTuple("INTERRUPTED", null);
            }

            Path dir = keys.get(key); //get next subdirectory path
            if (dir == null)
                return new myTuple("NULL DIRECTORY", null);

            for (WatchEvent<?> event : key.pollEvents()) {
                WatchEvent.Kind kind = event.kind();
                WatchEvent<Path> ev = cast(event);
                Path name = ev.context();
                Path child = dir.resolve(name);

                return new myTuple(event.kind().name(), child);
            }
            return null;
        //}
    }

    @SuppressWarnings("unchecked")
    static <T> WatchEvent<T> cast(WatchEvent<?> event) {
        return (WatchEvent<T>)event;
    }
}

我的客户:

import java.nio.file.attribute.*;
import java.nio.file.*;
import java.util.concurrent.TimeUnit;

public class newClient {
    public static void main(String[] args) throws IOException {

        Path folder = Paths.get(System.getProperty("user.dir"));
        WatchDir watcher = new WatchDir(folder, true);
        myTuple thisTuple;

    while (true) {
        thisTuple = watcher.processEvents();
        String event = thisTuple.getEvent();
        Path path = thisTuple.getPath();

        System.out.println(event+": "+path.toString());
    }
}
}
4

1 回答 1

0

您不重置密钥。再次阅读文档

处理完事件后,消费者调用密钥的重置方法来重置密钥,这允许向密钥发出信号并与进一步的事件一起重新排队。

大概在这里

       for (WatchEvent<?> event : key.pollEvents()) {
            WatchEvent.Kind kind = event.kind();
            WatchEvent<Path> ev = cast(event);
            Path name = ev.context();
            Path child = dir.resolve(name);

            return new myTuple(event.kind().name(), child);
        }
        key.reset();
        return null;
于 2014-12-06T09:33:09.797 回答