当 WatchService 监视的目录被删除时,其父目录不会立即在其 File 的 listFiles 方法中反映删除,因此无法删除。在整个服务被明确停止之前,父级的后果似乎是:
- 删除非空目录的推荐递归解决方案失败。
- 正常终止时未执行deleteOnExit
- 调用删除返回 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);
}
}
}
在 windows 上给出以下输出,这对应testDir
于文件系统上没有被删除。
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 方法可以实现这一点?