java 监控本地文件变化

直接贴代码


package event;

import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.*;

/**
 * @author likailong
 */
public class DirectoryWatcherImpl {
    private static final Logger LOGGER = LoggerFactory.getLogger(DirectoryWatcherImpl.class);

    private WatchService watchService;


    private final Map directories = new HashMap<>();

    private WatchEvent.Kind[] events;

    private static final ThreadFactory THREAD_FACTORY = new ThreadFactoryBuilder().setNameFormat("TtsWrapperService-pool-%d").build();
    private static ExecutorService EXECUTOR = null;
    private static LinkedBlockingQueue linkedBlockingQueue = new LinkedBlockingQueue<>(1024);


    public void watchDirectory(String path) {
        watchDirectory(Paths.get(path));
    }

    /**
     * 监控指定目录,不监控子目录
     *
     * @param path
     */
    public void watchDirectory(Path path) {
        registerDirectory(path);
    }

    /**
     * 监控指定的目录及其所有子目录
     *
     * @param path
     */
    public void watchDirectoryTree(String path) {
        watchDirectoryTree(Paths.get(path));
    }

    /**
     * 监控指定的目录及其所有子目录
     *
     * @param path
     */
    public void watchDirectoryTree(Path path) {
        registerDirectoryTree(path);
    }

    /**
     * 关闭监控线程
     */
    public void close() {
        EXECUTOR.shutdown();
    }

    private DirectoryWatcherImpl() {
    }


    private DirectoryWatcherImpl(final WatcherCallback watcherCallback, WatchEvent.Kind... events) {
        if (events.length == 0) {
            throw new RuntimeException("必须传入至少一个监控事件");
        }
        synchronized (DirectoryWatcherImpl.class) {
            EXECUTOR = new ThreadPoolExecutor(4, 20000, 0L,
                    TimeUnit.SECONDS, linkedBlockingQueue, THREAD_FACTORY, new ThreadPoolExecutor.AbortPolicy());
        }

        this.events = new WatchEvent.Kind[events.length];
        int i = 0;
        for (WatchEvent.Kind event : events) {
            this.events[i++] = event;
        }
        try {
            watchService = FileSystems.getDefault().newWatchService();
            EXECUTOR.submit(() -> watch(watcherCallback));
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private void watch(WatcherCallback watcherCallback) {
        while (true) {
            try {
                final WatchKey key = watchService.take();
                if (key == null) {
                    continue;
                }

                for (WatchEvent watchEvent : key.pollEvents()) {
                    final WatchEvent.Kind kind = watchEvent.kind();
                    //忽略无效事件
                    if (kind == StandardWatchEventKinds.OVERFLOW) {
                        continue;
                    }
                    final WatchEvent watchEventPath = (WatchEvent) watchEvent;
                    //path是相对路径(相对于监控目录)
                    final Path contextPath = watchEventPath.context();
                    //获取监控目录
                    final Path directoryPath = directories.get(key);
                    //得到绝对路径
                    final Path absolutePath = directoryPath.resolve(contextPath);

                    //判断事件类别
                    switch (kind.name()) {
                        case "ENTRY_CREATE":
                            if (Files.isDirectory(absolutePath, LinkOption.NOFOLLOW_LINKS)) {
                                //为新增的目录及其所有子目录注册监控事件
                                registerDirectoryTree(absolutePath);
                            } else {
                                LOGGER.info("新增文件:" + absolutePath);
                            }
                            break;
                        case "ENTRY_DELETE":
                            LOGGER.info("删除:" + absolutePath);
                            break;
                        case "ENTRY_MODIFY":
                            LOGGER.info("修改:" + absolutePath);
                            break;
                        default:
                            break;
                    }
                    //业务逻辑
                    watcherCallback.execute(kind, absolutePath.toAbsolutePath().toString());
                }
                boolean valid = key.reset();
                if (!valid) {
                    if (directories.get(key) != null) {
                        LOGGER.info("停止监控目录:" + directories.get(key));
                        directories.remove(key);
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private void registerDirectoryTree(Path path) {
        try {
            Files.walkFileTree(path, new SimpleFileVisitor() {
                @Override
                public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
                    registerDirectory(dir);
                    return FileVisitResult.CONTINUE;
                }
            });
        } catch (IOException ex) {
            LOGGER.error("监控目录失败:" + path.toAbsolutePath(), ex);
        }
    }

    private void registerDirectory(Path path) {
        try {
            LOGGER.info("监控目录:" + path);
            WatchKey key = path.register(watchService, events);
            directories.put(key, path);
        } catch (IOException ex) {
            LOGGER.error("监控目录失败:" + path.toAbsolutePath(), ex);
        }
    }

    public interface WatcherCallback {
        void execute(WatchEvent.Kind kind, String path);
    }


    public static void main(String[] args) {
        System.out.println("args = [" + linkedBlockingQueue.size() + "]");
        DirectoryWatcherImpl dictionaryWatcher = new DirectoryWatcherImpl(new WatcherCallback() {
            private long lastExecute = System.currentTimeMillis();

            @Override
            public void execute(WatchEvent.Kind kind, String path) {
                if (System.currentTimeMillis() - lastExecute > 1000) {
                    lastExecute = System.currentTimeMillis();
                    System.out.println("事件:" + kind.name() + " ,路径:" + path);
                }
            }
        }, StandardWatchEventKinds.ENTRY_CREATE,
                StandardWatchEventKinds.ENTRY_MODIFY,
                StandardWatchEventKinds.ENTRY_DELETE);
        //监控DIC目录及其所有子目录的子目录...递归
        dictionaryWatcher.watchDirectoryTree("/Users/likailong/Desktop");
        //只监控DIC2目录
        dictionaryWatcher.watchDirectory("/Users/likailong/Desktop");
    }


}

你可能感兴趣的:(java基础)