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

Java 遞歸獲取文件列表完整實現:目錄樹打印與數據收集

     編輯:Java 綜合教學

前言

文件系統遍歷是 Java IO 常見需求。本文提供遞歸實現目錄樹打印、文件信息收集的完整代碼,涵蓋層級縮進顯示、文件/目錄區分、數據結構化存儲。

完整代碼實現

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

public class FilesDemo {
    private static final String FILE_PATH = "./";
    private static List> fileList;

    public static void main(String[] args) {
        listFiles(new File(FILE_PATH), 1);
        
        // 可選:輸出收集的文件信息
        // for (Map item : fileList) {
        //     System.out.println("{name:" + item.get("name") + ",level:" + item.get("level") + "}");
        // }
    }

    public static void listFiles(File file, int level) {
        fileList = new ArrayList<>();
        Map item;
        File[] files = file.listFiles();
        
        if (files != null && files.length > 0) {
            for (File fileTemp : files) {
                String fileName = fileTemp.getName();
                System.out.println(getLevelPrefix(level) + fileName);
                
                if (fileTemp.isDirectory() && fileTemp.list().length > 0) {
                    listFiles(fileTemp, level + 1); // 遞歸遍歷子目錄
                } else {
                    // 收集文件信息
                    item = new HashMap<>();
                    item.put("name", fileTemp.getName());
                    item.put("level", String.valueOf(level));
                    fileList.add(item);
                }
            }
        } else {
            // 空目錄處理
            System.out.println(getLevelPrefix(level) + file.getName());
        }
    }

    // 生成層級縮進前綴
    public static String getLevelPrefix(int level) {
        StringBuilder sb = new StringBuilder();
        for (int i = 1; i < level; i++) {
            sb.append("  "); // 兩個空格縮進
        }
        sb.append("|--");
        return sb.toString();
    }
}

執行輸出範例

|--src
  |--main
    |--java
      |--com
        |--example
          |--App.java
      |--FilesDemo.java
  |--test
    |--resources
      |--config.properties
|--pom.xml
|--README.md

核心邏輯解析

1. 遞歸終止條件

  • file.listFiles() == null:非目錄或無權限
  • files.length == 0:空目錄
  • 文件節點:不再遞歸,直接收集信息

2. 層級縮進算法

// level=1: "|--"
// level=2: "  |--"
// level=3: "    |--"
public static String getLevelPrefix(int level) {
    StringBuilder sb = new StringBuilder();
    for (int i = 1; i < level; i++) {
        sb.append("  ");
    }
    sb.append("|--");
    return sb.toString();
}

3. 數據收集結構

List> fileList;
// 每個元素:{ "name": "App.java", "level": "3" }

進階優化方向

1. 使用 Files.walk API (Java 8+)

Files.walk(Paths.get("."))
    .filter(Files::isRegularFile)
    .forEach(path -> System.out.println(path));

2. 併發遍歷 (大目錄)

ForkJoinPool pool = new ForkJoinPool();
pool.submit(() -> Files.walk(Paths.get("."))
    .parallel()
    .filter(Files::isRegularFile)
    .forEach(System.out::println)).get();

3. 過濾器模式

// 僅收集 .java 文件
Files.walk(Paths.get("."))
    .filter(path -> path.toString().endsWith(".java"))
    .forEach(System.out::println);

4. 訪問者模式 (Java 7+)

Files.walkFileTree(Paths.get("."), new SimpleFileVisitor() {
    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
        System.out.println(file);
        return FileVisitResult.CONTINUE;
    }
    
    @Override
    public FileVisitResult visitFileFailed(Path file, IOException exc) {
        System.err.println("無法訪問: " + file);
        return FileVisitResult.CONTINUE;
    }
});

常見坑點

問題原因解決
NullPointerExceptionfile.listFiles() 返回 null先判斷 file.isDirectory() 且非 null
StackOverflowError符號鏈接循環記錄已訪問路徑 Set,檢測循環
權限拒絕無讀取權限目錄try-catch 包裹,記錄錯誤繼續
中文亂碼文件系統編碼不一致使用 Files API 自動處理編碼

總結

遞歸遍歷文件系統代碼簡潔直觀,適合中小型目錄。生產環境大規模遍歷建議使用 Files.walk 併流或訪問者模式,配合異常處理、符號鏈接檢測、編碼自適應,構建健壯的文件系統掃描工具。

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