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

Java 遞歸遍歷目錄獲取所有檔案路徑完整範例

     編輯:Java 相關知識

核心遞歸實現

import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class FileWalker {
    /** 遞歸收集指定目錄下所有檔案絕對路徑 */
    public static List<String> listAllFiles(String directoryPath) {
        List<String> result = new ArrayList<>();
        File root = new File(directoryPath);
        collect(root, result);
        return result;
    }

    private static void collect(File file, List<String> result) {
        if (!file.exists() || !file.isDirectory()) {
            return; // 不存在或非目錄
        }
        
        File[] children = file.listFiles();
        if (children == null) return; // IO 錯誤或權限不足
        
        for (File child : children) {
            if (child.isDirectory()) {
                collect(child, result); // 遞歸進入子目錄
            } else {
                result.add(child.getAbsolutePath()); // 收集檔案
            }
        }
    }
}

使用範例

public static void main(String[] args) {
    String path = "D:/Projects";
    List<String> files = FileWalker.listAllFiles(path);
    
    System.out.println("共找到 " + files.size() + " 個檔案:");
    files.forEach(System.out::println);
}

Java 7+ NIO.2 現代寫法 (推薦)

import java.nio.file.*;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;

public class ModernFileWalker {
    public static List<String> walk(String dir) throws IOException {
        try (Stream<Path> stream = Files.walk(Paths.get(dir))) {
            return stream
                .filter(Files::isRegularFile) // 只保留檔案,排除目錄
                .map(Path::toAbsolutePath)
                .map(Path::toString)
                .collect(Collectors.toList());
        }
    }
    
    // 限制深度
    public static List<String> walkMaxDepth(String dir, int maxDepth) throws IOException {
        try (Stream<Path> stream = Files.walk(Paths.get(dir), maxDepth)) {
            return stream.filter(Files::isRegularFile)
                .map(Path::toString).collect(Collectors.toList());
        }
    }
}

進階:過濾條件與大檔案處理

// 只收集 .java 檔案,且大小 > 1KB
Files.walk(Paths.get(dir))
    .filter(Files::isRegularFile)
    .filter(p -> p.toString().endsWith(".java"))
    .filter(p -> {
        try { return Files.size(p) > 1024; }
        catch (IOException e) { return false; }
    })
    .forEach(System.out::println);

// 處理海量檔案避免記憶體爆炸:使用 forEach 而非 collect
Files.walk(Paths.get(dir))
    .filter(Files::isRegularFile)
    .forEach(path -> processFile(path)); // 串流處理,不累積 List

效能與避坑指南

方案優點缺點適用場景
遞歸 File.listFiles()相容舊版 Java、邏輯直觀深層目錄棧溢位、無法中斷、效能一般Java 6 維護專案、簡單腳本
Files.walk() Stream函數式、可並行、支援過濾/限制深度需 Java 7+、大量檔案 collect 佔記憶體現代專案首選
Files.walkFileTree()完全控制 (可跳過、繼續、異常處理)代碼較繁瑣需自定義訪問邏輯、刪除目錄樹

常見陷阱

  • 符號連結循環:Files.walk 預設不跟隨符號連結,避免無限循環
  • 權限拒絕:listFiles() 返回 null,需判空;NIO 拋 AccessDeniedException,需 try-catch
  • 路徑過長:Windows 260 字元限制,Java 10+ 支援長路徑,或用 \\?\ 前綴
  • 隱藏檔案:預設包含隱藏檔,如需排除加 !Files.isHidden(p)

總結

現代 Java 專案**首選 Files.walk() Stream API**,代碼簡潔、支援函數式過濾、易於並行化。舊版專案或簡單腳本可用遞歸 File.listFiles(),注意判空與棧深度。處理超大目錄樹時,使用 forEach 串流處理避免記憶體壓力。

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