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

我可以用WatchService监视单个文件的更改吗(而不是整个目录)?

戚俊美
2023-03-14

当我试图注册一个文件而不是一个目录java时。尼奥。文件引发NotDirectoryException。我可以监听单个文件的更改,而不是整个目录吗?

共有3个答案

干善
2023-03-14

不,不可能注册文件,监视服务不这样工作。但是注册目录实际上会监视目录子目录(文件和子目录)上的更改,而不是目录本身的更改。

如果你想观看一个文件,那么你可以向观看服务注册包含该文件的目录。路径register()文档说明:

监视键java。尼奥。文件路径寄存器(WatchService watcher、Kind[]事件、修饰符…修饰符)引发IOException

向监视服务注册此路径下的文件。

在这个版本中,这个路径定位一个存在的目录。该目录在watch服务中注册,以便可以监视目录中的条目

然后,您需要处理条目上的事件,并通过检查事件的上下文值来检测与您感兴趣的文件相关的事件。上下文值表示条目的名称(实际上是相对于其父项路径的条目路径,它正是子项名称)。这里有一个例子。

傅志文
2023-03-14

其他答案是正确的,您必须查看目录并筛选特定文件。但是,您可能希望在后台运行线程。接受的答案可以无限期地阻止watchService。拿() 并且不关闭WatchService。适用于单独线程的解决方案可能如下所示:

public class FileWatcher extends Thread {
    private final File file;
    private AtomicBoolean stop = new AtomicBoolean(false);

    public FileWatcher(File file) {
        this.file = file;
    }

    public boolean isStopped() { return stop.get(); }
    public void stopThread() { stop.set(true); }

    public void doOnChange() {
        // Do whatever action you want here
    }

    @Override
    public void run() {
        try (WatchService watcher = FileSystems.getDefault().newWatchService()) {
            Path path = file.toPath().getParent();
            path.register(watcher, StandardWatchEventKinds.ENTRY_MODIFY);
            while (!isStopped()) {
                WatchKey key;
                try { key = watcher.poll(25, TimeUnit.MILLISECONDS); }
                catch (InterruptedException e) { return; }
                if (key == null) { Thread.yield(); continue; }

                for (WatchEvent<?> event : key.pollEvents()) {
                    WatchEvent.Kind<?> kind = event.kind();

                    @SuppressWarnings("unchecked")
                    WatchEvent<Path> ev = (WatchEvent<Path>) event;
                    Path filename = ev.context();

                    if (kind == StandardWatchEventKinds.OVERFLOW) {
                        Thread.yield();
                        continue;
                    } else if (kind == java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY
                            && filename.toString().equals(file.getName())) {
                        doOnChange();
                    }
                    boolean valid = key.reset();
                    if (!valid) { break; }
                }
                Thread.yield();
            }
        } catch (Throwable e) {
            // Log or rethrow the error
        }
    }
}

我试着从公认的答案和这篇文章开始工作。您应该能够将此线程与新的FileWatcher(新文件(“/home/me/myfile”))一起使用。启动()并通过调用线程上的stopThread()停止它。

陈宜修
2023-03-14

只需在目录中筛选所需文件的事件:

final Path path = FileSystems.getDefault().getPath(System.getProperty("user.home"), "Desktop");
System.out.println(path);
try (final WatchService watchService = FileSystems.getDefault().newWatchService()) {
    final WatchKey watchKey = path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY);
    while (true) {
        final WatchKey wk = watchService.take();
        for (WatchEvent<?> event : wk.pollEvents()) {
            //we only register "ENTRY_MODIFY" so the context is always a Path.
            final Path changed = (Path) event.context();
            System.out.println(changed);
            if (changed.endsWith("myFile.txt")) {
                System.out.println("My file has changed");
            }
        }
        // reset the key
        boolean valid = wk.reset();
        if (!valid) {
            System.out.println("Key has been unregisterede");
        }
    }
}

在这里我们检查更改的文件是否为“myFile.txt”,如果是则执行任何操作。

 类似资料:
  • 问题内容: 如何在Linux( ext3 文件系统)中监视 整个目录树 的更改? __ 当前,该目录包含大约 3,000个子目录* 中的大约 一百万个文件 ,这些 文件 分为三个目录级别。 * 这些文件大多是小文件(<1kb,有些则最大100 kb)。这是一种队列,我需要知道在发生这种情况的5-10秒内何时创建,删除文件或修改其内容。 我知道这里有 inotify 和sorting,但是AFAIK

  • 问题内容: 这就是问题所在:我们想要一个哈希表,其条目是线程安全的。 假设我的哈希表为,并且我想安全地增加条目线程之一的值:可以吗? 然后,每当我想增加一个条目时: 我认为它比ConcurrentHashMap更好,因为它仅锁定一个条目,而不像ConcurrentHashMap使用存储桶并将一组条目锁定在一起。 更重要的是,我不知道如何安全地使用COncurrenHashMap对其进行递增。例如,

  • 问题内容: 是否可以“监视”指令上的ui更改?像这样的东西: 问题答案: 是。您可以使用,如果你在属性利用插值。 但是,如果这不是一个插值属性,并且您希望它可以从应用程序中的其他位置更改(绝对不建议这样做,请阅读Common Pitfalls ),那么函数可以返回: 无论如何,对您来说最好的方法可能是更改更改元素类的代码。它何时更改?

  • 问题内容: 我有我的mysql数据库的mysqldump备份,该数据库由我们的所有表组成,大约440兆。我想从mysqldump恢复仅其中一张表的内容。这可能吗?从理论上讲,我可以剪掉重建所需表的部分,但我什至不知道如何有效地编辑该大小的文本文档。 问题答案: 您可以尝试使用sed以便仅提取所需的表。 假设表的名称为,文件mysql.dump是包含您的大型转储的文件: 这将在文件中复制位于与下一个

  • 问题内容: 就像一个类似的SO问题一样,我正在尝试监视Linux机器上的目录以添加新文件,并希望在这些新文件到达时立即对其进行处理。关于实现此最佳方法的任何想法? 问题答案: 看inotify。 使用inotify,您可以监视用于文件创建的目录。

  • 问题内容: 我在这里写的主要是关于从哪里开始的建议。我已经实现了一个类,该类将使用Java的WatchService递归监视目录。它可以很好地检测更改,但是我注意到了一个致命的缺陷:我无法删除包含正在监视的目录的正在监视的目录。这似乎是WatchService的限制。 我还稍微研究了Apache的VFS FileListener,但是在花了大约6个小时的时间来围绕它构建某种包装之前,我想也许我只是