如何监视文件夹和子文件夹的更改

2022-09-02 19:48:25

我正在尝试监视特定文件夹的更改,然后如果其中发生任何添加/版本/删除,我需要获取该文件夹及其子文件夹中所有文件的更改类型。我正在使用它,但它只监视单个路径,它不处理子文件夹。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<String> filesLog = new ArrayList<String>();
            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

有没有更好的解决方案?


答案 1

A 只监视您注册的 s。它不会以递归方式通过这些路径。WatchServicePath

作为注册路径给出/Root

/Root
    /Folder1
    /Folder2
        /Folder3

如果 中有变化,它不会捕获它。Folder3

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

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

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


答案 2

递归注册将按照Sotirios的指示工作。这将有效地注册当前存在的每个目录/子目录。

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

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

这将监视整个子树的更改和添加目录和子目录的帐户。

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


推荐