如何在Java中检测文件系统的变化

4
我想知道如何在Java中高效地实现文件系统更改?比如说,我有一个文件在一个文件夹中,我修改了那个文件。我希望Java能尽快通知我这个更改(如果可能的话不要频繁轮询)。
因为我认为我可以每隔几秒钟调用java.io.file.lastModified,但我不喜欢这种解决方案的听起来。
alfred@alfred-laptop:~/testje$ java -version
java version "1.6.0_18"
Java(TM) SE Runtime Environment (build 1.6.0_18-b07)
Java HotSpot(TM) Server VM (build 16.0-b13, mixed mode)
4个回答

8

看看JNotify,它可以执行这种类型的监控。

Java 7将拥有一些更高级的API(WatchService),用于此类工作,这将消除在支持此功能的操作系统上进行轮询的需要。


1
如果我没记错的话,JNotify需要特定于操作系统的DLL。虽然可能不如性能(是的,还不是一个真正的词),但JPoller提供了纯Java实现。 - Kaleb Pederson
所以我想在使用Java7之前,这总是一个小技巧,因为我认为Jpoller会疯狂轮询。 JNotify不是本地的.. - Alfred
不太确定您所说的JNotify不是本地的意思。它确实需要特定于操作系统的DLL /库。 - Brian Agnew
我将更加仔细地查看JNotify,但从我迄今读到的JNotify中得知,它使用特定于系统的解决方案。我希望我错过了某些东西,只需在我的类路径(在NetBeans中)中放置一个单独的jar文件。接下来调用一个带有回调或其他内容的函数并得到通知。 - Alfred
2
实际上,JNotify只调用特定于Win、OS X和Linux的操作系统库。它不支持其他操作系统,并且没有轮询机制。Java 7 WatchService基本上与JNotify相同,但如果没有文件系统本地监视设施可用,则会回退到轮询。 - Jono

1
使用JNotify,您只需要将jnotify.jar添加到构建路径中,并将两个dll文件即jnotify.dll和jnotify_64bit.dll放置在jdk的lib目录下。一个演示程序是:
package jnotify;

import net.contentobjects.jnotify.JNotify;
import net.contentobjects.jnotify.JNotifyListener;

public class MyJNotify {
  public void sample() throws Exception {
    String path = "Any Folder location here which you want to monitor";
    System.out.println(path);
    int mask = JNotify.FILE_CREATED | JNotify.FILE_DELETED
            | JNotify.FILE_MODIFIED | JNotify.FILE_RENAMED;
    boolean watchSubtree = true;
    int watchID = JNotify
            .addWatch(path, mask, watchSubtree, new Listener());
    Thread.sleep(1000000);
    boolean res = JNotify.removeWatch(watchID);
    if (!res) {
        System.out.println("Invalid");
    }
}

class Listener implements JNotifyListener {
    public void fileRenamed(int wd, String rootPath, String oldName,
            String newName) {
        print("renamed " + rootPath + " : " + oldName + " -> " + newName);
    }

    public void fileModified(int wd, String rootPath, String name) {
        print("modified " + rootPath + " : " + name);
    }

    public void fileDeleted(int wd, String rootPath, String name) {
        print("deleted " + rootPath + " : " + name);
    }

    public void fileCreated(int wd, String rootPath, String name) {
        print("created " + rootPath + " : " + name);
    }

    void print(String msg) {
        System.err.println(msg);
    }
}
public static void main(String[] args) {
    try {
        new MyJNotify().sample();
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
}

1

我怀疑是否有一种纯Java的方法来实现这个。操作系统提供了API来监视文件系统活动。您可能需要调用这些API。


我并没有仔细研究过,但我认为这实际上是Java7中新的文件系统API所涉及的一部分。归根结底,它当然需要来自文件系统或操作系统本身的支持。 - Fredrik

1

有一个Apache软件包可进行文件系统监控:commons.io.monitor。

文档

示例

据我所知,即使您可以控制频率,仍需要轮询。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接