当前位置: 首页 > 知识库问答 >
问题:

Java文件夹/文件监视

邴墨竹
2023-03-14

我试图构建一个应用程序,监视文件夹及其子文件夹,以检测文件的创建或修改。要观看的文件总数将日益增加。

我曾尝试使用java nio WatchService和apache常见的FileAlteration观察者。WatchService有时会在WatchKey被获取之后和重置之前发生文件创建/修改时丢失事件。由于FileAlterationeller是基于轮询的,因此当文件计数增加时性能也会下降。

构建这样一个应用程序的最佳方法是什么?

共有1个答案

长孙星汉
2023-03-14

谢谢@DuncG。在浏览了提到的示例后,我找到了解决问题的方法。

如果有人面临相同的问题,请添加此示例代码。

在示例中,我将所有事件添加到一个集合中(这将删除重复事件),并在WatchKey为空时处理保存的事件。在处理保存的事件时,新目录将注册到WatchService。

package com.filewatcher;

import java.io.File;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardWatchEventKinds;
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.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class WatchService implements Runnable {

private static final long POLL_DELAY = 3;

private static final Logger LOGGER = LoggerFactory.getLogger(WatchService.class);

private final WatchService watcher;

private final Map<WatchKey, Path> keys;

private final Set<Path> events = new HashSet<Path>();

public WatchService(Path dir) throws IOException {
    this.watcher = FileSystems.getDefault().newWatchService();
    this.keys = new HashMap<WatchKey, Path>();
    walkAndRegisterDirectories(dir);
}

@Override
public void run() {
    while (true) {
        try {
            WatchKey key;
            try {
                key = watcher.poll(POLL_DELAY, TimeUnit.SECONDS);
            } catch (InterruptedException x) {
                return;
            }

            if (key != null) {
                Path root = keys.get(key);
                for (WatchEvent<?> event : key.pollEvents()) {
                    Path eventPath = (Path) event.context();
                    if (eventPath == null) {
                        System.out.println(event.kind());
                        continue;
                    }

                    Path fullPath = root.resolve(eventPath);
                    events.add(fullPath);
                }

                boolean valid = key.reset();
                if (!valid) {
                    keys.remove(key);
                }
            } else {
                if (events.size() > 0) {
                    processEvents(events);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

/**
 * Process events and register new directory with watch service
 * @param events
 * @throws IOException
 */
private void processEvents(Set<Path> events) throws IOException {
    for (Path path : events) {
        // register directory with watch service if its not already registered
        if (Files.isDirectory(path, LinkOption.NOFOLLOW_LINKS) && !this.keys.containsValue(path)) {
            registerDirectory(path);
            // Since new directory was not registered, get all files inside the directory.
            // new/modified files after this will get notified by watch service
            File[] files = path.toFile().listFiles();
            for (File file : files) {
                LOGGER.info(file.getAbsolutePath());
            }
        } else {
            LOGGER.info(path.toString());
        }
    }
    // clear events once processed
    events.clear();
}

/**
 * Register a directory and its sub directories with watch service
 * @param root folder
 * @throws IOException
 */
private void walkAndRegisterDirectories(final Path root) throws IOException 
{
    Files.walkFileTree(root, new SimpleFileVisitor<Path>() {
        @Override
        public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
            registerDirectory(dir);
            return FileVisitResult.CONTINUE;
        }
    });
}

/**
 * Register a directory with watch service
 * @param directory
 * @throws IOException
 */
  private void registerDirectory(Path dir) throws IOException {
    WatchKey key = dir.register(this.watcher, StandardWatchEventKinds.ENTRY_CREATE,
            StandardWatchEventKinds.ENTRY_MODIFY);
    this.keys.put(key, dir);
  }
}

public class FileWatcherApplication implements CommandLineRunner {
    @Value("${filewatch.folder}")
    private String rootPath;

    public static void main(String[] args) {
        SpringApplication.run(FileWatcherApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        File rootFolder = new File(rootPath);
        if (!rootFolder.exists()) {
            rootFolder.mkdirs();
        }

        new Thread(new WatchService(Paths.get(rootPath)), "WatchThread").start();
    }
}
 类似资料:
  • 问题内容: 我有一个名为“数据”的文件夹。此文件夹有一个名为“收件箱”的子文件夹,其中有多个“ .txt”文件。可以修改“数据”文件夹,最后会有多个带有“收件箱”子文件夹和“ .txt”文件的子文件夹。我需要监视“收件箱”文件夹中的“数据”文件夹和“ .txt”文件。我怎样才能做到这一点? INotify只是监视文件夹,并在创建子文件夹时弹出事件。创建“ .txt”文件(在哪个文件夹中)时,如何弹

  • 如何替换正在运行的应用程序中的某些文件(主要活动文件),例如:。, /src/main/java/[com.package.name]/home.java /src/main/res/layout/home.xml 与其他文件一起: /src/main/assets/home.java/src/main/assets/home.xml 我试过: 但它不起作用,我怀疑是错误的文件路径。如果我尝试:

  • 我从我的IntelliJ Java 15 Gradle项目的resources文件夹中的子文件夹加载文件时遇到问题...

  • 问题内容: 我开发了一个应用程序,可以从用户选择的文件夹中读取文件。它显示每个文件中有多少行代码。我只希望Java文件显示在文件选择器(扩展名为.java的文件)中。下面是我的代码: 我也进行了编辑,但是仍然无法正常工作,请告知请告知如何仅读取扩展名为.java的文件,换句话说,请仅从文件夹中读取java文件,请告知 问题答案: 您需要一个FilenameFilter。这应该为您工作:

  • 本文向大家介绍Java使用递归复制文件夹及文件夹,包括了Java使用递归复制文件夹及文件夹的使用技巧和注意事项,需要的朋友参考一下 递归调用copyDir方法实现,查询源文件目录使用字节输入流写入字节数组,如果目标文件目录没有就创建目录,如果迭代出是文件夹使用字节输出流对拷文件,直至源文件目录没有内容。 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐喊教程。

  • 我有一个像这样的文件夹 应用程序 供应商 引导程序 公开的 文件夹 img 当我从url访问时http://example.com/img/img.png它工作,但当我喜欢访问http://example.com/img/我得到禁止403,我需要的是重定向或显示该页面没有找到我的。htaccess看起来像这样。 选项-多视图选项-索引重写引擎打开