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

PHP 非遞歸遍歷目錄:使用堆疊實現完整文件掃描

     編輯:PHP 相關知識

前言

在 PHP 開發中,遍歷目錄下所有文件(包含子目錄)是常見需求。雖然遞歸寫法直觀,但深層目錄可能導致堆疊溢位或效能問題。本文介紹如何使用堆疊(Stack)模擬遞歸,實現非遞歸的目錄遍歷,並提供兩種實用代碼範例供參考。

核心思路:堆疊模擬遞歸

遞歸本質是系統自動管理的呼叫堆疊。我們可以用陣列手動模擬:

  1. 建立一個陣列 $stack,將起始目錄壓入。
  2. 當堆疊不為空時,彈出一個目錄掃描。
  3. 掃描結果若為目錄,壓入堆疊;若為文件,收集到結果陣列。
  4. 重複直到堆疊為空。

範例一:標準非遞歸掃描函數 scanfiles()

此函數回傳所有文件的完整路徑陣列,兼容 Windows/Unix 路徑分隔符。

/**
 * 非遞歸掃描目錄下所有文件
 * @param string $dir 目錄路徑
 * @return array 文件路徑陣列
 */
function scanfiles($dir) {
    if (!is_dir($dir)) return [];
    // 統一路徑分隔符並確保結尾有斜線
    $dir = rtrim(str_replace('\\', '/', $dir), '/') . '/';
    
    $stack = [$dir];
    $files = [];
    
    do {
        $currentDir = array_pop($stack);
        $entries = scandir($currentDir);
        
        foreach ($entries as $entry) {
            if ($entry === '.' || $entry === '..') continue;
            $path = $currentDir . $entry;
            
            if (is_dir($path)) {
                $stack[] = $path . '/';
            } elseif (is_file($path)) {
                $files[] = $path;
            }
        }
    } while ($stack);
    
    return $files;
}

範例二:簡易版 scanAll() 並解決順序問題

此版本直接輸出路徑,邏輯更簡潔。注意 scandir() 返回順序導致壓棧順序反向,需用 array_reverse() 修正。

/**
 * 遍歷目錄並輸出所有文件/目錄路徑
 * @param string $dir 起始目錄
 */
function scanAll($dir) {
    $stack = [$dir];
    
    while (count($stack) > 0) {
        $path = array_pop($stack);
        echo $path . "\r\n";
        
        if (is_dir($path)) {
            // 反轉順序,使輸出與遞歸版一致
            $children = array_reverse(scandir($path));
            foreach ($children as $child) {
                if ($child !== '.' && $child !== '..') {
                    $stack[] = $path . '/' . $child;
                }
            }
        }
    }
}

對比:遞歸寫法 scanAll2()

function scanAll2($dir) {
    echo $dir . "\r\n";
    if (is_dir($dir)) {
        $children = scandir($dir);
        foreach ($children as $child) {
            if ($child !== '.' && $child !== '..') {
                scanAll2($dir . '/' . $child);
            }
        }
    }
}

效能與適用場景

  • 遞歸:代碼簡潔,適合淺層目錄、快速原型。
  • 非遞歸:避免堆疊溢位,適合深層目錄、長時間運行的腳本、記憶體受限環境。
  • 實測差異微小,除非目錄深度超過百層或文件數極大。

總結

掌握堆疊模擬遞歸是進階 PHP 開發者的基本功。根據項目需求選擇合適方式,並注意路徑分隔符兼容與掃描順序控制,即可高效完成目錄遍歷任務。

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