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

PHP 遞歸掃描目錄的五種方法效能對比:glob vs dir vs opendir vs scandir vs SPL

     編輯:PHP 綜合知識

專案中常需遞歸遍歷目錄(如掃描模板、清理快取、建立檔案索引)。PHP 提供多種目錄讀取 API,本文實測五種主流寫法並附效能基準測試,幫助選型。

五種實現方式

1. glob() 模式匹配

<?php
function scanGlob(string $path, array &$result): void {
    foreach (glob($path . '/*') as $file) {
        if (is_dir($file)) {
            scanGlob($file, $result);
        } else {
            $result[] = realpath($file);
        }
    }
}
?>

2. dir() + read() 物件導向

<?php
function scanDirRead(string $path, array &$result): void {
    $dir = dir($path);
    while (($file = $dir->read()) !== false) {
        if ($file === '.' || $file === '..') continue;
        $full = realpath($path . '/' . $file);
        $result[] = $full;
        if (is_dir($full)) scanDirRead($full, $result);
    }
    $dir->close();
}
?>

3. opendir() + readdir() 程序式(經典)

<?php
function scanOpenDir(string $path, array &$result): void {
    $handle = opendir($path);
    while (($file = readdir($handle)) !== false) {
        if ($file === '.' || $file === '..') continue;
        $full = realpath($path . '/' . $file);
        $result[] = $full;
        if (is_dir($full)) scanOpenDir($full, $result);
    }
    closedir($handle);
}
?>

4. scandir() 陣列一次讀取

<?php
function scanScandir(string $path, array &$result): void {
    foreach (scandir($path) as $file) {
        if ($file === '.' || $file === '..') continue;
        $full = realpath($path . '/' . $file);
        $result[] = $full;
        if (is_dir($full)) scanScandir($full, $result);
    }
}
?>

5. SPL DirectoryIterator(現代 OO 風格)

<?php
function scanSPL(string $path, array &$result): void {
    $iterator = new DirectoryIterator($path);
    foreach ($iterator as $fileInfo) {
        if ($fileInfo->isDot()) continue;
        $full = $fileInfo->getRealPath();
        $result[] = $full;
        if ($fileInfo->isDir()) scanSPL($full, $result);
    }
}
?>

效能基準測試(Xdebug 計時)

測試環境:PHP 7.4,SSD,約 5 萬檔案專案目錄。

方法耗時(秒)記憶體峰值評價
glob()0.164低最快,模式匹配靈活
opendir/readdir0.233低經典穩定,資源需手動 close
scandir()0.240中一次讀全陣列,大目錄記憶體較高
dir()/read()0.243低OO 封裝,較 opendir 略慢
SPL DirectoryIterator0.330中功能最豐富(權限、時間、類型),但效能最差

選型建議

  • 單純遞歸列檔、追求速度 → glob() 或 opendir/readdir。
  • 需檔案元資料(mtime、size、權限) → SPL DirectoryIterator 或 FilesystemIterator(可過濾 . / ..)。
  • 大目錄(>10萬檔) → 避免 scandir() 一次載入陣列,改用迭代器或 glob() 分批。
  • 現代專案 → 推薦 RecursiveDirectoryIterator + RecursiveIteratorIterator 一行搞定:
<?php
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS));
foreach ($files as $file) {
    // $file 是 SplFileInfo 物件
    echo $file->getRealPath() . PHP_EOL;
}
?>

避坑提醒

  1. realpath() 會解析符號連結並快取,大量呼叫可能觸發快取滿;可用 clearstatcache()。
  2. 權限不足目錄會拋出 Permission denied,建議 try-catch 或 @ 抑制。
  3. Windows 路徑長度限制(260 字元)可能導致深層目錄掃描失敗。

根據業務場景選對工具,效能差異可達 2 倍以上。

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