首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java 遞歸刪除文件/目錄工具類:字符串路徑版與 File 對象版完整實現

     編輯:Java 綜合教學

Java 遞歸刪除文件/目錄工具類:字符串路徑版與 File 對象版完整實現

文件刪除看似簡單,實則暗藏目錄非空、路徑分隔符、符號鏈接、權限不足、并發修改等坑。本文提供兩個生產可用的靜態工具方法:delete(String path) 與 deleteAllFiles(File file),並對比差異、補充 NIO.2 現代寫法與避坑清單。

版本一:傳入字符串路徑

public static void delete(String path) {
    File file = new File(path);
    // 1. 不存在直接返回
    if (!file.exists()) return;

    // 2. 是文件直接刪除
    if (file.isFile()) {
        file.delete();
        return;
    }

    // 3. 是目錄:遞歸刪除子項
    if (file.isDirectory()) {
        String[] children = file.list();
        if (children == null) return; // 權限不足或 IO 錯誤

        // 關鍵:確保路徑以分隔符結尾
        if (!path.endsWith(File.separator)) {
            path += File.separator;
        }

        for (String child : children) {
            delete(path + child); // 遞歸
        }
    }

    // 4. 最後刪除空目錄自身
    file.delete();
}

版本二:傳入 File 對象(推薦,更面向對象)

public static void deleteAllFiles(File file) {
    if (!file.exists()) return;

    if (file.isFile()) {
        file.delete();
        return;
    }

    if (file.isDirectory()) {
        File[] children = file.listFiles(); // 直接獲取 File[],無需手動拼路徑
        if (children == null) return;

        for (File child : children) {
            deleteAllFiles(child); // 遞歸傳 File 對象
        }
    }

    file.delete(); // 刪除空目錄
}

核心差異對比

維度字符串版 delete(String)File 版 deleteAllFiles(File)
路徑拼接手動 path + File.separator + child,易出錯File.listFiles() 直接返回完整 File 對象,無需拼接
性能多次創建 File 對象,字符串拼接開銷僅創建必要 File 對象,較優
符號鏈接可能誤刪鏈接目標同樣問題,需額外判斷 Files.isSymbolicLink()
推薦場景舊代碼兼容、配置文件讀取路徑新代碼、內部調用、流式處理

現代寫法:Java 7+ NIO.2 Files.walkFileTree(最強健)

import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;

public static void deletePath(Path path) throws IOException {
    if (!Files.exists(path)) return;

    Files.walkFileTree(path, 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 {
            if (exc != null) throw exc;
            Files.delete(dir); // 刪除空目錄
            return FileVisitResult.CONTINUE;
        }
    });
}

優勢:

  • 自動處理深度遞歸、異常傳播、符號鏈接(可選 FileVisitOption.FOLLOW_LINKS)。
  • 支持 Files.deleteIfExists 靜默忽略不存在。
  • 可併發安全刪除(配合 FileLock)。

避坑清單(必讀)

  1. file.delete() 返回 boolean:必須檢查返回值,失敗拋異常或記錄日志,否則靜默失敗極難排查。
  2. list()/listFiles() 返回 null:非目錄、IO 錯誤、權限不足時返回 null,必須判空否則 NPE。
  3. 符號鏈接:刪除鏈接文件會刪除目標內容(JDK 行為),生產環境需用 Files.isSymbolicLink() 判斷並決定策略。
  4. 并發修改:遞歸過程中目錄被外部修改(文件新增/刪除),可能遺漏或報錯。關鍵目錄建議加文件鎖或使用原子移動後再刪。
  5. Windows 文件佔用:文件被進程打開時 delete() 返回 false,需關閉句柄或重啟進程。
  6. 垃圾回收延遲:大量文件刪除後磁盤空間未立即釋放,屬文件系統行為,非 Java 問題。

生產級工具類模板

public final class FileUtils {
    private FileUtils() {}

    public static boolean deleteQuietly(Path path) {
        try {
            deletePath(path);
            return true;
        } catch (IOException e) {
            log.warn("Delete failed: {}", path, e);
            return false;
        }
    }

    // 內部使用 NIO.2 實現...
}
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved