如何查看文件夹和子文件夹以进行更改

我正在尝试查看特定文件夹以进行更改,然后如果在其中发生任何添加/编辑/删除,我需要获取该文件夹及其子文件夹中所有文件的更改类型。 我正在使用WatchService ,但它只观看单个路径,它不处理子文件夹。

这是我的方法:

 try { WatchService watchService = pathToWatch.getFileSystem().newWatchService(); pathToWatch.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE); // loop forever to watch directory while (true) { WatchKey watchKey; watchKey = watchService.take(); // This call is blocking until events are present // Create the list of path files ArrayList filesLog = new ArrayList(); if(pathToWatch.toFile().exists()) { File fList[] = pathToWatch.toFile().listFiles(); for (int i = 0; i < fList.length; i++) { filesLog.add(fList[i].getName()); } } // Poll for file system events on the WatchKey for (final WatchEvent event : watchKey.pollEvents()) { printEvent(event); } // Save the log saveLog(filesLog); if(!watchKey.reset()) { System.out.println("Path deleted"); watchKey.cancel(); watchService.close(); break; } } } catch (InterruptedException ex) { System.out.println("Directory Watcher Thread interrupted"); return; } catch (IOException ex) { ex.printStackTrace(); // Loggin framework return; } 

就像我之前说的那样,我只获取所选路径中的文件的日志,并且我想要查看所有文件夹和子文件夹文件,例如:

例1:

 FileA (Created) FileB FileC FolderA FileE FolderA FolderB FileF 

例2:

 FileA FileB (Modified) FileC FolderA FileE FolderA FolderB FileF 

有没有更好的解决方案?

WatchServiceWatchService您注册的Path 。 它不会递归地通过这些路径。

/Root作为注册路径

 /Root /Folder1 /Folder2 /Folder3 

如果Folder3有更改,它将无法捕获它。

您可以自己递归注册目录路径

 private void registerRecursive(final Path root) throws IOException { // register all subfolders Files.walkFileTree(root, new SimpleFileVisitor() { @Override public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { dir.register(watchService, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY); return FileVisitResult.CONTINUE; } }); } 

现在WatchService将通知Path root所有子文件夹中的所有更改,即。 您传递的Path参数。

递归注册将像Sotirios指出的那样工作。 这有效地注册了当前存在的每个目录/子目录。

您也可以导入和使用* com.sun.nio.file.ExtendedWatchEventModifier.FILE_TREE *,如下所示:

 dir.register(watcher, standardEventsArray, ExtendedWatchEventModifier.FILE_TREE); 

这将观察整个子树的更改并考虑添加的目录和子目录。

否则,您必须监视任何新目录/子目录并注册它们。 删除目录层次结构的部分也存在问题,因为每个注册的目录都有一个句柄,因此在删除结构的某些部分时需要首先删除(最低)子目录。

我使用Java 8流和lambdas实现了类似的东西。

递归文件夹发现实现为Consumer @FunctionalInterface:

  final Map keys = new HashMap<>(); Consumer register = p -> { if (!p.toFile().exists() || !p.toFile().isDirectory()) { throw new RuntimeException("folder " + p + " does not exist or is not a directory"); } try { Files.walkFileTree(p, new SimpleFileVisitor() { @Override public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { LOG.info("registering " + dir + " in watcher service"); WatchKey watchKey = dir.register(watcher, new WatchEvent.Kind[]{ENTRY_CREATE}, SensitivityWatchEventModifier.HIGH); keys.put(watchKey, dir); return FileVisitResult.CONTINUE; } }); } catch (IOException e) { throw new RuntimeException("Error registering path " + p); } }; 

每次创建新文件夹时都会调用上面的代码,以便在以后的阶段动态添加文件夹。 完整的解决方案和更多细节。