Java WatchService API

在这个例子中,我们将学习使用java 8 WatchServiceAPI 观察目录及其中的所有子目录和文件。

如何注册Java 8 WatchService

要注册WatchService,请获取目录路径和使用path.register()方法。

Path path = Paths.get(".");

WatchService watchService =  path.getFileSystem().newWatchService();

path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY);

观看改变事件

要获取其中的目录和文件发生的更改,请使用watchKey.pollEvents()以流的形式返回所有更改事件的集合的方法。

WatchKey watchKey = null;

while (true) {

    watchKey = watchService.poll(10, TimeUnit.MINUTES);

    if(watchKey != null) {

        watchKey.pollEvents().stream().forEach(event -> System.out.println(event.context()));

    }

    watchKey.reset();

}

密钥仍然有效,直到:

  • 它通过调用取消方法显式取消,或者
  • 隐式取消,因为对象不再可访问,或
  • 关闭手表服务。

如果您重复使用相同的密钥在循环内多次获取更改事件,则不要忘记调用watchKey.reset()将密钥再次设置为就绪状态的方法。

请注意,诸如如何检测事件,及时性以及是否保留其排序等几个因素在很大程度上取决于底层操作系统。某些更改可能导致一个操作系统中的单个条目,而类似的更改可能会导致另一个操作系统中的多个事件。

观察目录,子目录和变更文件示例

在这个例子中,我们将看到一个示例,其中包含一个包含所有子目录和文件的目录。我们将维护监视密钥和目录的映射,Map<WatchKey, Path> keys以正确识别已修改的目录。

下面的方法将单个目录注册到观察者,然后将目录和密钥存储在地图中。

private void registerDirectory(Path dir) throws IOException

{

    WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);

    keys.put(key, dir);

}

我们将在遍历目录结构时递归调用此方法,并为我们遇到的每个目录调用此方法。

private void walkAndRegisterDirectories(final Path start) throws IOException {

    // register directory and sub-directories

    Files.walkFileTree(start, new SimpleFileVisitor<Path>() {

        @Override

        public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throwsIOException {

            registerDirectory(dir);

            return FileVisitResult.CONTINUE;

        }

    });

}

请注意,在创建新目录的任何时候,我们都会将其注册到watchservice,并将新的密钥添加到地图中。

WatchEvent.Kind kind = event.kind();

if (kind == ENTRY_CREATE) {

    try {

        if (Files.isDirectory(child)) {

            walkAndRegisterDirectories(child);

        }

    catch (IOException x) {

        // do something useful

    }

}

将上述所有内容与逻辑一起处理事件,完整示例如下所示:

package com.howtodoinjava.examples;

 

import static java.nio.file.StandardWatchEventKinds.*;

 

import java.io.IOException;

import java.nio.file.FileSystems;

import java.nio.file.FileVisitResult;

import java.nio.file.Files;

import java.nio.file.Path;

import java.nio.file.Paths;

import java.nio.file.SimpleFileVisitor;

import java.nio.file.WatchEvent;

import java.nio.file.WatchKey;

import java.nio.file.WatchService;

import java.nio.file.attribute.BasicFileAttributes;

import java.util.HashMap;

import java.util.Map;

 

public class Java8WatchServiceExample {

 

    private final WatchService watcher;

    private final Map<WatchKey, Path> keys;

 

    /**

     * Creates a WatchService and registers the given directory

     */

    Java8WatchServiceExample(Path dir) throws IOException {

        this.watcher = FileSystems.getDefault().newWatchService();

        this.keys = new HashMap<WatchKey, Path>();

 

        walkAndRegisterDirectories(dir);

    }

 

    /**

     * Register the given directory with the WatchService; This function will be called by FileVisitor

     */

    private void registerDirectory(Path dir) throws IOException

    {

        WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);

        keys.put(key, dir);

    }

 

    /**

     * Register the given directory, and all its sub-directories, with the WatchService.

     */

    private void walkAndRegisterDirectories(final Path start) throws IOException {

        // register directory and sub-directories

        Files.walkFileTree(start, new SimpleFileVisitor<Path>() {

            @Override

            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throwsIOException {

                registerDirectory(dir);

                return FileVisitResult.CONTINUE;

            }

        });

    }

 

    /**

     * Process all events for keys queued to the watcher

     */

    void processEvents() {

        for (;;) {

 

            // wait for key to be signalled

            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()) {

                @SuppressWarnings("rawtypes")

                WatchEvent.Kind kind = event.kind();

 

                // Context for directory entry event is the file name of entry

                @SuppressWarnings("unchecked")

                Path name = ((WatchEvent<Path>)event).context();

                Path child = dir.resolve(name);

 

                // print out event

                System.out.format("%s: %s\n", event.kind().name(), child);

 

                // if directory is created, and watching recursively, then register it and its sub-directories

                if (kind == ENTRY_CREATE) {

                    try {

                        if (Files.isDirectory(child)) {

                            walkAndRegisterDirectories(child);

                        }

                    catch (IOException x) {

                        // do something useful

                    }

                }

            }

 

            // 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;

                }

            }

        }

    }

 

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

        Path dir = Paths.get("c:/temp");

        new Java8WatchServiceExample(dir).processEvents();

    }

}

运行此程序并在给定输入中更改文件和目录后,您将在控制台中注意到捕获的事件。

输出:

ENTRY_CREATE:c:\ temp \ New文件夹
ENTRY_DELETE:c:\ temp \ New文件夹
ENTRY_CREATE:c:\ temp \ data
ENTRY_CREATE:c:\ temp \ data \ New Text Document.txt
ENTRY_MODIFY:c:\ temp \ data
ENTRY_DELETE:c:\ temp \ data \ New Text Document.txt
ENTRY_CREATE:c:\ temp \ data \ tempFile.txt
ENTRY_MODIFY:c:\ temp \ data
ENTRY_MODIFY:c:\ temp \ data \ tempFile.txt
ENTRY_MODIFY:c:\ temp \ data \ tempFile.txt
ENTRY_MODIFY:c:\ temp \ data \ tempFile.txt

这就是使用Java 8 WatchService API监视文件更改并处理它们的简单示例。

猜你喜欢

转载自blog.csdn.net/u010675669/article/details/86503783