首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 更多程式設計知識

Java 遞歸實現目錄遍歷與刪除:完整代碼範例與最佳實踐

     編輯:更多程式設計知識

在 Java 開發中,遍歷目錄結構與遞歸刪除資料夾是常見的檔案操作需求。本文提供兩個完整、可直接執行的實作範例,涵遞歸讀取、遞歸刪除,並說明關鍵 API 與注意事項。

核心 API 回顧

  • File.list():回傳字串陣列(檔名),不含路徑。
  • File.listFiles():回傳 File 物件陣列,含完整路徑,**推薦使用**。
  • File.delete():僅能刪除「檔案」或「空目錄」。非空目錄必須先遞歸刪除內容物。
  • File.isDirectory() / isFile():判斷類型。

範例一:基礎版(使用 list() + 字串拼接路徑)

package test.com;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

public class ReadFile {

    /**
     * 遞歸讀取指定路徑下的所有檔案名稱
     * @param filepath 目錄路徑
     * @return true 表示完成
     */
    public static boolean readfile(String filepath) throws FileNotFoundException, IOException {
        File file = new File(filepath);
        if (!file.exists()) {
            throw new FileNotFoundException("路徑不存在: " + filepath);
        }

        if (file.isFile()) {
            System.out.println("檔案: " + file.getName());
        } else if (file.isDirectory()) {
            String[] filelist = file.list();
            if (filelist == null) return true; // 空目錄或無權限

            for (String name : filelist) {
                // 注意:此處需手動處理路徑分隔符,建議用 File 建構子
                File child = new File(filepath + File.separator + name);
                if (child.isFile()) {
                    System.out.println("檔案: " + child.getName());
                } else if (child.isDirectory()) {
                    readfile(child.getAbsolutePath()); // 遞歸
                }
            }
        }
        return true;
    }

    /**
     * 遞歸刪除目錄及其所有內容
     * @param delpath 待刪除路徑
     * @return true 表示成功
     */
    public static boolean deletefile(String delpath) throws IOException {
        File file = new File(delpath);
        if (!file.exists()) return true; // 不存在視為成功

        if (file.isFile()) {
            return file.delete();
        } else if (file.isDirectory()) {
            File[] children = file.listFiles();
            if (children != null) {
                for (File child : children) {
                    deletefile(child.getAbsolutePath()); // 遞歸刪除子項
                }
            }
            // 此時目錄應為空,可刪除自身
            return file.delete();
        }
        return false;
    }

    public static void main(String[] args) {
        try {
            // 測試讀取
            readfile("C:/Users/SW/Desktop/TestFolder");
            // 測試刪除(謹慎使用!)
            // deletefile("D:/Temp/TestDelete");
            System.out.println("操作完成");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

範例二:進階版(使用 listFiles()、專案相對路徑、詳細資訊輸出)

package otherstudy;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

public class TestReadFile {

    /**
     * 取得專案 WebRoot 絕對路徑(適用於部署在 Servlet 容器的專案)
     */
    String getProjectPath() {
        String path = this.getClass().getResource("/").getPath(); // /d:/workspace/project/WebRoot/WEB-INF/classes/
        return path.substring(1, path.indexOf("WEB-INF/classes"));
    }

    /**
     * 遞歸讀取並印出詳細資訊
     */
    public static boolean readAllFile(String filepath) throws FileNotFoundException, IOException {
        File file = new File(filepath);
        if (!file.exists()) throw new FileNotFoundException("路徑不存在: " + filepath);

        if (file.isFile()) {
            printFileInfo(file, "檔案資訊");
        } else if (file.isDirectory()) {
            System.out.println("\n資料夾內容列表: " + file.getAbsolutePath());
            File[] fileList = file.listFiles();
            if (fileList != null) {
                for (File child : fileList) {
                    if (child.isFile()) {
                        printFileInfo(child, "  檔案");
                    } else if (child.isDirectory()) {
                        readAllFile(child.getAbsolutePath()); // 遞歸
                    }
                }
            }
        }
        return true;
    }

    private static void printFileInfo(File f, String prefix) {
        System.out.println(prefix + ": " + f.getName());
        System.out.println("  相對路徑: " + f.getPath());
        System.out.println("  絕對路徑: " + f.getAbsolutePath());
    }

    /**
     * 遞歸刪除並印出刪除日誌
     */
    public static boolean deleteFile(String delpath) throws FileNotFoundException, IOException {
        File file = new File(delpath);
        if (!file.exists()) return true;

        if (file.isFile()) {
            System.out.println("刪除檔案: " + file.getAbsolutePath());
            return file.delete();
        } else if (file.isDirectory()) {
            File[] fileList = file.listFiles();
            if (fileList != null) {
                for (File child : fileList) {
                    deleteFile(child.getAbsolutePath());
                }
            }
            System.out.println("刪除目錄: " + file.getAbsolutePath());
            return file.delete();
        }
        return false;
    }

    public static void main(String[] args) {
        TestReadFile trf = new TestReadFile();
        String xmlPath = trf.getProjectPath() + "testDocs";
        try {
            readAllFile(xmlPath);
            // deleteFile(xmlPath); // 謹慎啟用
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

關鍵最佳實踐總結

  1. 優先使用 listFiles():回傳 File 陣列,自動處理路徑分隔符,跨平台相容性更好。
  2. 檢查 null 回傳:list() 與 listFiles() 在目錄不存在、無讀取權限、或非目錄時會回傳 null,必須判斷避免 NullPointerException。
  3. 使用 File.separator:而非硬編碼 "/" 或 "\\",確保 Windows/Linux/macOS 相容。
  4. 刪除順序:先子後父:必須先遞歸刪除所有子檔案/子目錄,最後刪除空的父目錄。
  5. 異常處理:IO 操作拋出 IOException,建議在呼叫端統一捕獲並記錄日誌,避免中斷主流程。
  6. 生產環境建議:Java 7+ 可使用 Files.walkFileTree() (NIO.2) 實現更高效、更安全的目錄遍歷與刪除,支援訪問選項與屬性讀取。

Java 7+ NIO.2 現代寫法(補充)

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

public class ModernDelete {
    public static void deleteDirectory(Path path) throws IOException {
        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;
            }
        });
    }
}

掌握遞歸目錄操作是 Java 檔案處理的基本功。建議在新專案中優先採用 NIO.2 API,舊專案維護時參考本文範例進行安全重構。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved