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<WatchKey, Path> 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<Path> watchEventPath = (WatchEvent<Path>) 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<Path>() {
                @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");
    }


}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值