WatchServiceによって監視されているディレクトリが削除された場合、その親ディレクトリは File のlistFilesメソッドに削除をすぐに反映せず、削除できません。サービス全体が明示的に停止されるまで、親の結果は次のようになります。
- 空でないディレクトリを削除するための推奨される再帰的な解決策は失敗します。
- 正常終了時にdeleteOnExitが行われていない
- deleteの呼び出しはfalse を返し、ファイルシステムには影響しません。
実証するために、このテスト コードは次のとおりです。
import java.io.*;
import java.nio.file.*;
class DirectoryTester {
static WatchService watcher;
static {
try{watcher = FileSystems.getDefault().newWatchService();}
catch (IOException e) {e.printStackTrace();}
}
public static void main(String[] args) throws IOException {
String SEPARATE = System.getProperty("file.separator");
String testDirName = System.getProperty("user.dir") + SEPARATE + "testDir";
String subDirName = testDirName + SEPARATE + "subDir";
String fileName = subDirName + SEPARATE +"aFile";
create(fileName);
Paths.get(subDirName).register(watcher, StandardWatchEventKinds.ENTRY_DELETE);
delete(new File(testDirName));
}
static void create(String nameOfFile) throws IOException {
new File(nameOfFile).getParentFile().mkdirs();
Files.createFile(Paths.get(nameOfFile));
System.out.println("Created " + nameOfFile);
}
static void delete(File toDelete) throws IOException {
if (toDelete.isDirectory())
for (File c : toDelete.listFiles())
delete(c);
int numContainedFiles = toDelete.listFiles() != null ? toDelete.listFiles().length : 0;
if (!toDelete.delete()) {
System.out.println("Failed to delete " + toDelete + " containing " + numContainedFiles);
}
else {
System.out.println("Deleted " + toDelete + " containing " + numContainedFiles);
}
}
}
testDir
ファイルシステムで削除されていないことに対応する、Windowsで次の出力が得られます。
Created C:\Dropbox\CodeSpace\JavaTestbed\src\testDir\subDir\aFile
Deleted C:\Dropbox\CodeSpace\JavaTestbed\src\testDir\subDir\aFile containing 0
Deleted C:\Dropbox\CodeSpace\JavaTestbed\src\testDir\subDir containing 0
Failed to delete C:\Dropbox\CodeSpace\JavaTestbed\src\testDir containing 1
削除後にブレークポイントを設定するsubDir
と、ファイル システム上で実際に削除されていることがわかります。ブレークポイントから再開すると、最後の削除が成功します。これは、監視サービス スレッドによって行われた変更の可視性に問題がある可能性があることを示唆しています。ここで何が起こっているのか、そしてそれがバグなのか知っている人はいますか? 私が実際にやろうとしているのは、他のディレクトリの監視を停止せずに監視されているディレクトリを削除することです.APIによって提供される登録解除パスメソッドがないように見える場合、これを達成する他の標準的なJavaの方法は何ですか?