Java 1.7删除目录遇DirectoryNotEmptyException问题求助(Windows资源管理器打开时)
解决Windows资源管理器打开时Java NIO删除目录失败的问题
这个问题我之前在Windows环境开发时也踩过一模一样的坑,本质是Windows系统的文件锁定机制在搞鬼——当资源管理器打开目标目录时,系统会暗中持有该目录的句柄(比如用来生成缩略图、缓存文件预览信息),这时候Java调用Files.delete(dir)时,系统会判定目录仍在被使用,从而抛出DirectoryNotEmptyException。至于调试时没问题,是因为断点暂停给了系统足够时间释放这些临时句柄,而运行时程序执行速度快,句柄还没来得及释放就触发了删除操作。
下面给你两个可行的解决办法:
1. 增加重试机制(推荐)
既然是时序问题,我们可以在删除目录时加入重试逻辑,给系统一点时间释放资源管理器的句柄。修改你的postVisitDirectory方法如下:
@Override public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { if(exc == null){ int maxRetries = 3; int retryDelay = 200; // 每次重试间隔200毫秒 boolean deleteSuccess = false; while (maxRetries > 0 && !deleteSuccess) { try { Files.delete(dir); deleteSuccess = true; } catch (DirectoryNotEmptyException e) { maxRetries--; // 等待一段时间后重试 try { Thread.sleep(retryDelay); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); // 把中断异常包装成IO异常抛出 throw new IOException("Interrupted while waiting to delete directory", ie); } } } if (!deleteSuccess) { throw new IOException("Failed to delete directory after " + 3 + " retries: " + dir.toString()); } return FileVisitResult.CONTINUE; } throw exc; }
这个办法不需要额外依赖,对用户也友好,不需要强制关闭资源管理器窗口,大部分场景下都能解决问题。
2. 检测并提示用户关闭资源管理器(备选)
如果重试机制依然偶尔失败,你可以在抛出最终异常前,检测目标目录是否被资源管理器占用(不过Java本身没有直接API做这个,需要借助JNI或者第三方库比如jna),然后弹出提示让用户关闭对应的资源管理器窗口。不过这个方案复杂度较高,除非重试机制无法满足你的需求,否则不推荐。
总结一下,优先用重试机制就能搞定这个Windows特有的问题。
内容的提问来源于stack exchange,提问作者Navneet
相关产品推荐
相关产品推荐

