0
以下のコードは問題を明らかにしています:ファイルの変更を監視するためのJava 7インターフェイスは、ファイルのオープンを報告しますが、実際のコンテンツの変更は報告しません。java.nio.files.StandardWatchEventKinds.ENTRY_MODIFYはファイル内容の変更を報告しませんか?
コンテンツの変更を検出する方法はありますか?私のプログラムは、利用可能な限り新しいコンテンツを読む必要があります。
イベントリスナーによって報告される唯一の長さは、0(ファイルのオープン直後)です。 - イベント
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
出力での問題:ジャワ(TM)SEランタイム環境(1.7.0-b147をビルド)に
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();
}
}
}
出力:問題を再現する
コンパイル可能なソースファイルのオープン時に1回だけ発生し、実際の書き込みやファイルのクローズ時に発生することはありません。