2014-12-06 53 views
1

我想同步兩個文件夾及其在客戶端和服務器之間的子目錄。我有一個修改版本this class,我在下面發佈。在我的Client類中,我創建了一個WatchDir對象,並在無限循環中調用其processEvents()方法。該方法返回一個myTuple對象(包含事件類型和路徑對象的結構),如果事件被註冊,則返回null,否則返回null。問題是,這似乎只適用於目錄中發生的第一個事件(即,如果我將文件添加到監視的文件夾中,我的WatchDir object.processEvents()將返回一個帶有ENTRY_CREATE事件的Tuple,並且永遠不會返回另一個Tuple for其他文件添加/刪除/修改後發生)。我希望processEvents每次發生某個事件時都會不斷調用(因此無限)。謝謝你的幫助!不斷閱讀java WatchEvents

我修改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()); 
    } 
} 
} 

回答

0

你不復位的關鍵。閱讀docs再次:

一旦事件被處理消費者調用鍵的 復位方法重置允許鑰匙發出信號,並與其他事件 重新排隊的關鍵。

這裏大概

 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; 
+0

我不得不返工的代碼位,以避免內返回的循環,但復位是我錯過了什麼。謝謝 – WongWray 2014-12-06 21:24:13