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

C# 遞歸列舉目錄下所有檔案的工具類別實作

     編輯:關於C語言

前言

在檔案系統操作中,遞歸遍歷目錄樹是常見需求。本文提供一個可直接使用的 DirList 類別,支援指定起始路徑、選擇是否遞歸子目錄,並回傳 ArrayList 包含所有檔案完整路徑(空目錄以 /// 前綴標記)。

完整程式碼

using System;
using System.IO;
using System.Collections;

namespace DSclub
{
    /// 
    /// 目錄遞歸列舉工具類別
    /// 
    public class DirList
    {
        private string _initPath;
        private bool _recursive;

        /// 
        /// 預設建構子:從 C:\ 開始,不遞歸
        /// 
        public DirList()
        {
            _initPath = @"C:\";
            _recursive = false;
        }

        /// 
        /// 指定起始路徑建構子
        /// 
        public DirList(string startPath)
        {
            _initPath = startPath;
            _recursive = false;
        }

        /// 
        /// 是否遞歸子目錄
        /// 
        public bool Recursive
        {
            get => _recursive;
            set => _recursive = value;
        }

        /// 
        /// 取得檔案清單(使用建構子指定的路徑與模式)
        /// 
        public ArrayList GetFiles() => GetFiles(_initPath, _recursive);

        /// 
        /// 靜態方法:取得指定路徑的檔案清單
        /// 
        /// 起始目錄
        /// 是否遞歸子目錄
        /// 檔案路徑集合,空目錄以 "///" 開頭標記
        public static ArrayList GetFiles(string path, bool recursive)
        {
            ArrayList result = new ArrayList();

            // 驗證路徑存在
            if (!Directory.Exists(path))
                throw new ApplicationException($"路徑不存在或非目錄: {path}");

            // 取得目前目錄下所有檔案
            string[] files = Directory.GetFiles(path);
            foreach (string file in files)
                result.Add(file);

            // 空目錄標記
            if (files.Length == 0)
                result.Add("///" + path);

            // 遞歸處理子目錄
            if (recursive)
            {
                string[] dirs = Directory.GetDirectories(path);
                foreach (string dir in dirs)
                    result.AddRange(GetFiles(dir, true));
            }

            return result;
        }
    }
}

使用範例

// 範例 1:列出 D:\Projects 所有檔案(含子目錄)
DirList lister = new DirList(@"D:\Projects");
lister.Recursive = true;
ArrayList allFiles = lister.GetFiles();

foreach (string f in allFiles)
    Console.WriteLine(f);

// 範例 2:靜態方法直接呼叫(僅當前目錄)
ArrayList currentOnly = DirList.GetFiles(@"C:\Temp", false);

輸出格式說明

  • 一般檔案:完整路徑,如 D:\Projects\A\test.cs
  • 空目錄:///D:\Projects\EmptyFolder(方便識別無檔案資料夾)

已知限制與改進方向

限制改進建議
未處理 UnauthorizedAccessException(系統資料夾無權限)加入 try-catch 略過無權限目錄,或記錄錯誤日誌
未處理重新解析點/連結點(Junction/Symlink)導致無限遞歸維護 HashSet<string> 記錄已訪問實體路徑
使用 ArrayList 非泛型集合改為 List<string> 提供型別安全與效能
大量檔案記憶體壓力大改為 IEnumerable<string> 配合 yield return 串流輸出
無檔案過濾功能加入 searchPattern 參數支援萬用字元

現代化重構範例 (.NET Core / .NET 5+)

using System;
using System.Collections.Generic;
using System.IO;

public static class DirectoryExtensions
{
    /// 
    /// 遞歸列舉檔案(串流輸出,記憶體友善)
    /// 
    public static IEnumerable EnumerateFilesRecursive(
        string rootPath, string searchPattern = "*", 
        SearchOption option = SearchOption.AllDirectories)
    {
        if (!Directory.Exists(rootPath))
            throw new DirectoryNotFoundException(rootPath);

        var visited = new HashSet(StringComparer.OrdinalIgnoreCase);
        var stack = new Stack();
        stack.Push(Path.GetFullPath(rootPath));

        while (stack.Count > 0)
        {
            string current = stack.Pop();
            string realPath = Path.GetFullPath(current);

            if (!visited.Add(realPath)) continue; // 防止符號連結循環

            try
            {
                foreach (string file in Directory.EnumerateFiles(current, searchPattern))
                    yield return file;

                if (option == SearchOption.AllDirectories)
                {
                    foreach (string dir in Directory.EnumerateDirectories(current))
                        stack.Push(dir);
                }
            }
            catch (UnauthorizedAccessException) { /* 忽略無權限目錄 */ }
            catch (IOException) { /* 忽略 I/O 錯誤 */ }
        }
    }
}

使用現代化版本

foreach (string file in DirectoryExtensions.EnumerateFilesRecursive(@"D:\Projects", "*.cs"))
    Console.WriteLine(file);

// 只列出當前目錄
foreach (string file in Directory.EnumerateFiles(@"D:\Projects", "*.cs", SearchOption.TopDirectoryOnly))
    Console.WriteLine(file);
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved