初學者常寫的遞歸刪除代碼存在兩大缺陷:路徑拼接錯誤(傳遞文件名而非完整路徑)與 空目錄未刪除。本文給出修正版遞歸實現,並推薦 Java 7+ Files.walkFileTree 一行式方案。
public static void deleteDir(String dirPath) {
File file = new File(dirPath);
if (file.isDirectory()) {
String[] files = file.list();
for (String f : files) {
deleteDir(f); // 錯誤:f 只是文件名,非完整路徑!
}
} else {
if (file.isFile()) file.delete();
}
// 缺失:刪除空目錄本身
}
file.list() 返回不帶路徑的文件名,遞歸調用時會在當前工作目錄下尋找,導致 FileNotFound 或誤刪同名文件。file.delete() 清理空目錄。list() 返回 null(目錄不存在/無權限)的情況。public static boolean deleteDir(File dir) {
if (dir == null || !dir.exists()) return true;
if (dir.isDirectory()) {
File[] children = dir.listFiles();
if (children != null) {
for (File child : children) {
if (!deleteDir(child)) return false; // 任一失敗即回滾
}
}
}
return dir.delete(); // 文件或空目錄統一刪除
}
關鍵點:使用 listFiles() 返回 File[](含完整路徑),尾部 dir.delete() 覆蓋文件與空目錄兩種情況。
import java.nio.file.*;
import java.io.IOException;
public static void deleteDir(Path root) throws IOException {
Files.walkFileTree(root, new SimpleFileVisitor() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Files.delete(file); // 先刪文件
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
Files.delete(dir); // 後刪目錄(底層已空)
return FileVisitResult.CONTINUE;
}
});
}
優勢:自動處理符號鏈接、權限異常、深度優先順序,代碼極簡且線程安全。
FileUtils.deleteDirectory(new File(dirPath)); // 內部已處理所有邊界情況
生產環境首選 Commons IO 或 NIO.2,避免重複造輪子。
Files.isWritable(path)。IOException,需捕獲並重試或提示用戶關閉占用進程。