java.nio.files.StandardWatchEventKinds.ENTRY_MODIFY是否报告文件内容没有变化?

时间:2011-09-13 01:14:51

标签: java events nio java-7

下面的代码演示了这个问题:用于监视文件更改的java 7接口报告文件打开,但不报告内容的实际更改。

有没有办法检测内容变化?我的程序需要尽快阅读新内容。

事件侦听器报告的唯一长度为0(在打开文件后立即)。

重现问题的可编辑来源:

import java.io.Writer;
import java.nio.charset.Charset;
import java.nio.file.ClosedWatchServiceException;
import java.nio.file.Files;
import java.nio.file.Path;
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.FileAttribute;

class NioModifiedProblem {
    public static void println(String str) {
        System.out.println(str);
    }
    public static void printFileInfo(Path path) {
        try {
            println(String.format("File %s, size %d, modified %s", path, Files.size(path), Files.getLastModifiedTime(path)));
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        String data = "Some not too long string goes here. Goes. Goes.";
        try {
            final Path path = Files.createTempFile("nioProblem", ".tmp", new FileAttribute[0]);
            path.toFile().deleteOnExit();
            println("Created");
            printFileInfo(path);

            Thread thread = new Thread() {
                public void run() {
                    try {
                        final Path parent = path.getParent();
                        final WatchService service = parent.getFileSystem().newWatchService();
                        WatchKey key = parent.register(service, StandardWatchEventKinds.ENTRY_MODIFY);
                        try {
                            while (true) {
                                for (WatchEvent<?> event : service.take().pollEvents()){
                                    Path modifiedPath = parent.resolve((Path)event.context());
                                    println("Path "+modifiedPath+" modified EVENT."); // This is printed only once, on file opening.
                                    printFileInfo(modifiedPath);
                                }
                            }
                        } catch (ClosedWatchServiceException e) {
                            println("Service closed");
                        }
                    } catch (Throwable e) {
                        e.printStackTrace();
                    } finally {
                        println("Watcher thread exiting");
                    }
                }
            };
            thread.setDaemon(true);
            thread.start();

            Thread.sleep(1000);
            Writer fw = Files.newBufferedWriter(path, Charset.forName("UTF-8"));
            println("Opened");
            printFileInfo(path);

            Thread.sleep(1000);
            fw.write(data);
            println("Written");
            printFileInfo(path);

            fw.close();
            println("Closed");
            printFileInfo(path);

            Thread.sleep(1000);
            println("Sleeped");
            printFileInfo(path);
            return;
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }
}

Java(TM)SE运行时环境(版本1.7.0-b147)上的输出:

Created
File C:\Users\b\AppData\Local\Temp\nioProblem190636654560972941.tmp, size 0, modified 2011-09-14T16:20:06.782Z
Opened
Path C:\Users\b\AppData\Local\Temp\nioProblem190636654560972941.tmp modified EVENT.
File C:\Users\b\AppData\Local\Temp\nioProblem190636654560972941.tmp, size 0, modified 2011-09-14T16:20:07.807Z
File C:\Users\b\AppData\Local\Temp\nioProblem190636654560972941.tmp, size 0, modified 2011-09-14T16:20:07.807Z
Written
File C:\Users\b\AppData\Local\Temp\nioProblem190636654560972941.tmp, size 0, modified 2011-09-14T16:20:07.807Z
Closed
File C:\Users\b\AppData\Local\Temp\nioProblem190636654560972941.tmp, size 47, modified 2011-09-14T16:20:08.81Z
Sleeped
File C:\Users\b\AppData\Local\Temp\nioProblem190636654560972941.tmp, size 47, modified 2011-09-14T16:20:08.81Z

输出事件的问题仅在文件打开时引发一次,并且在实际写入或文件关闭时从不引发。

Download source

1 个答案:

答案 0 :(得分:1)

在pollEvents()之后应该重置WatchedKey以便能够接受更多事件。