2017-02-28 110 views
0

对于我当前的项目,我需要使用WatchService来跟踪给定目录中的事件。我的代码还主要是基于关闭的Oracles WatchService tutorial example使用WatchService忽略文件事件(创建,修改,删除)

然而,我需要它仅限于文件夹唯一事件(例如ENTRY_CREATE C:\ TEMP \ folder_a)。

我试图做的是把目录的内容 的初始快照,以及每个内容的路径存储到任何dirCachefileCache

如果一个新的事件被注册这应该被检查:

  • 是事件上下文中文件fileCache
  • 是事件上下文的新文件( - > Files.i sRegularFile)

因此,这两个新的文件事件都应该被丢弃或者已经存在于缓存中的文件中的事件。

但印刷出来的事件产生

ENTRY_DELETE:C:\ TEMP \ k.txt

的文件,但没有ENTRY_CREATE或ENTRY_MODIFY。

我在做什么错?我没有正确检查缓存吗?还是完全不同的东西?

下面是当前代码库:

public class Main { 
    public static void main(String[] args) { 
     try { 
      new DirectoryWatcher(Paths.get("C:\\temp")).processEvents(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

DirectoryWatcher

package service; 

import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE; 
import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE; 
import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY; 
import static java.nio.file.StandardWatchEventKinds.OVERFLOW; 

import java.io.IOException; 
import java.nio.file.FileSystems; 
import java.nio.file.Files; 
import java.nio.file.Path; 
import java.nio.file.WatchEvent; 
import java.nio.file.WatchEvent.Kind; 
import java.nio.file.WatchKey; 
import java.nio.file.WatchService; 
import java.util.HashMap; 
import java.util.Map; 

/** 
* Slightly modified version of Oracle 
* example file WatchDir.java 
*/

public class DirectoryWatcher { 
    private final Path path; 
    private final WatchService watcher; 
    private final Map<WatchKey,Path> keys; 
    private PathSnapshot pathSnapshot; 
    private boolean trace = false; 

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

/** 
* Register the given directory with the WatchService 
*/ 
private void register(Path dir) throws IOException { 
    WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY); 
    if (trace) { 
     Path prev = keys.get(key); 
     if (prev == null) { 
      System.out.format("register: %s\n", dir); 
     } else { 
      if (!dir.equals(prev)) { 
       System.out.format("update: %s -> %s\n", prev, dir); 
      } 
     } 
    } 
    keys.put(key, dir); 
} 

public DirectoryWatcher(Path dir) throws IOException { 
    this.watcher = FileSystems.getDefault().newWatchService(); 
    this.keys = new HashMap<WatchKey,Path>(); 
    this.path = dir; 
    this.pathSnapshot = new PathSnapshot(dir); 

    register(dir); 
    // enable trace after initial registration 
    this.trace = true; 
} 

/** 
* Process all events for keys queued to the watcher 
*/ 
void processEvents() { 
    for (;;) { 

     // wait for key to be signaled 
     WatchKey key; 
     try { 
      key = watcher.take(); 
     } catch (InterruptedException x) { 
      return; 
     } 

     Path dir = keys.get(key); 
     if (dir == null) { 
      System.err.println("WatchKey not recognized!!"); 
      continue; 
     } 

     for (WatchEvent<?> event: key.pollEvents()) { 
      Kind<?> kind = event.kind(); 

      // TBD - provide example of how OVERFLOW event is handled 
      if (kind == OVERFLOW) { 
       continue; 
      } 

      // Context for directory entry event is the file name of entry 
      WatchEvent<Path> ev = cast(event); 
      Path name = ev.context(); 
      Path child = dir.resolve(name); 
      this.updateDirContent(); 
      /* 
      * currently: creating file events are neglected 
      * but deleting a file creates an event which is printed 
      * TODO: disregard delete event if sent from file 
      */ 
      boolean isFile = Files.isRegularFile(child); 
      if (pathSnapshot.isInFileCache(child)|| isFile) { 
       //disregard the event if file 
       event = null; 
      } else { 
       // print out event 
       System.out.format("%s: %s\n", event.kind().name(), child); 
      } 
     } 

     // reset key and remove from set if directory no longer accessible 
     boolean valid = key.reset(); 
     if (!valid) { 
      keys.remove(key); 
      // all directories are inaccessible 
      if (keys.isEmpty()) { 
       break; 
      } 
     } 
    } 
} 

private void updateDirContent() { 
    this.pathSnapshot = pathSnapshot.updateSnapshot(path); 

} 
} 

PathSnapshot

package service; 

import java.io.IOException; 
import java.nio.file.Files; 
import java.nio.file.Path; 
import java.nio.file.Paths; 
import java.util.ArrayList; 
import java.util.stream.Stream; 

public class PathSnapshot { 
    public ArrayList<Path> dirCache = new ArrayList<Path>(); 
    public ArrayList<Path> fileCache = new ArrayList<Path>(); 

    public PathSnapshot(Path dir) { 
     try { 
      Stream<Path> rawDirContent = Files.walk(
        dir, 1); 

      Object[] dirContent = rawDirContent.toArray(); 
      rawDirContent.close(); 

      sortIntoCache(dirContent, dir); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    private void sortIntoCache(Object[] dirContent, Path rootdir) { 
     for (Object object : dirContent) { 
      //create path from element 
      Path objectPath = Paths.get(object.toString()); 
      //skip start path/the root directory 
      if (object.equals(rootdir)) { 
       continue; 
      } else if (Files.isRegularFile(objectPath)) { 
       fileCache.add(objectPath); 
      } else if (Files.isDirectory(objectPath)) { 
       dirCache.add(objectPath); 
      } 
     } 
    } 

    public boolean isInFileCache(Path path) { 
     if (fileCache.contains(path)) { 
      return true; 
     } else { 
      return false; 
     } 
    } 

    public boolean isInDirCache(Path path) { 
     if (dirCache.contains(path)) { 
      return true; 
     } else { 
      return false; 
     } 
    } 

    public PathSnapshot updateSnapshot(Path dir){ 
     return new PathSnapshot(dir); 
    } 
} 

回答

0

您现在收听的所有可能的前夕从文件系统nts,所以没有更多的要求。如果操作系统不提供更多的事件和更详细的信息,Java就无能为力。一些复杂的文件系统操作不是由一个事件代表,而是由一系列基本事件代表。所以你必须充分利用这些事件,并且必须解释一系列事件实际上意味着什么。

+0

但是,不应该我自己的实施工作吗?如果创建了一个文件,我更新* PathSnapshot *,并且如果发生删除事件,则上下文将类似于“C:\ temp \ a_file.txt”,如果这是针对fileCache进行检查的,则将其注册为文件事件并将其丢弃。 –

相关问题