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

PHP 遍歷目錄檔案與子目錄:opendir/readdir 完整教學

     編輯:PHP 相關知識

核心函數:opendir()、readdir()、closedir()

函數說明
opendir(path, context)開啟目錄控制代碼,成功回傳 resource,失敗回傳 false
readdir(handle)讀取目錄下一個項目(檔案/子目錄/./..),到達末尾回傳 false
closedir(handle)關閉目錄控制代碼,釋放資源

基礎範例:列出所有項目(含 . 與 ..)

<?php
$dir = opendir("bkjia"); // 相對路徑
while (($file = readdir($dir)) !== false) {
    echo "filename: " . $file . "<br />";
}
closedir($dir);
?>

輸出:

filename: .
filename: ..
filename: cat.gif
filename: dog.gif
filename: food
filename: horse.gif

進階:只取得子目錄名稱(過濾檔案與特殊項目)

<?php
function getSubDirs($dir) {
    $subdirs = [];
    if (!$dh = opendir($dir)) return $subdirs;
    
    while ($f = readdir($dh)) {
        if ($f === '.' || $f === '..') continue; // 跳過特殊項目
        $path = $dir . '/' . $f; // 完整路徑
        if (is_dir($path)) {
            $subdirs[] = $f; // 或存完整路徑 $path
        }
    }
    closedir($dh);
    return $subdirs;
}

$arr = getSubDirs("tmp");
print_r($arr);
/* 輸出範例:
Array (
    [0] => Hello
    [1] => NowaMagic
)
*/
?>

遞迴遍歷:樹狀結構輸出(兩種寫法)

寫法一:使用 dir() 物件導向風格

<?php
function tree($directory) {
    $mydir = dir($directory);
    echo "<ul>\n";
    while ($file = $mydir->read()) {
        $full = "$directory/$file";
        if (is_dir($full) && $file !== '.' && $file !== '..') {
            echo "<li><font color=\"#ff00cc\"><b>$file</b></font></li>\n";
            tree($full); // 遞迴
        } else {
            echo "<li>$file</li>\n";
        }
    }
    echo "</ul>\n";
    $mydir->close();
}

echo "<h2>目錄為粉紅色</h2><br>\n";
tree("./bkjia");
?>

寫法二:使用 opendir/readdir 程序風格

<?php
function listDir($dir) {
    if (is_dir($dir)) {
        if ($dh = opendir($dir)) {
            while (($file = readdir($dh)) !== false) {
                $full = $dir . "/" . $file;
                if (is_dir($full) && $file !== '.' && $file !== '..') {
                    echo "<b><font color='red'>目錄:</font></b>$file<br><hr>";
                    listDir($full . "/");
                } else {
                    if ($file !== '.' && $file !== '..') {
                        echo "$file<br>";
                    }
                }
            }
            closedir($dh);
        }
    }
}

listDir("./bkjia");
?>

現代替代方案:SPL DirectoryIterator(PHP 5+)

更物件導向、支援迭代器介面、自動過濾 . 與 ..:

<?php
$iterator = new RecursiveIteratorIterator(
    new RecursiveDirectoryIterator('./bkjia', RecursiveDirectoryIterator::SKIP_DOTS)
);

foreach ($iterator as $file) {
    $indent = str_repeat('  ', $iterator->getDepth());
    echo $indent . ($file->isDir() ? '[D] ' : '[F] ') . $file->getFilename() . "\n";
}
?>

效能與選擇建議

方法優點缺點適用場景
opendir/readdir底層控制細緻、記憶體效率高需手動過濾 . ..、程式碼較冗長大量檔案、需精細控制、舊版 PHP
dir() 物件OO 風格、內建 read/close功能同 opendir偏好 OO 風格專案
glob()支援萬用字元模式匹配一次載入所有結果佔記憶體模式匹配、中小目錄
scandir()一次取得陣列、語法簡潔大目錄記憶體壓力大需陣列操作、中小目錄
SPL Iterators標準化、支援過濾、遞迴、鏈式操作物件開銷略高現代專案首選

常見陷阱避坑

  • readdir() 回傳 false 判斷:必須用 !== false,因檔名可能為 "0" 導致 while($file = readdir()) 提早結束
  • 路徑拼接:使用 DIRECTORY_SEPARATOR 或 /(Windows 也支援)
  • 權限問題:opendir() 失敗時回傳 false,建議加 @ 抑制警告並自行處理
  • 符號連結:is_dir() 會跟隨連結,遞迴時可能陷入循環,需用 is_link() 檢查

總結

掌握 opendir/readdir/closedir 基礎三部曲是理解 PHP 檔案系統操作的關鍵。現代專案建議直接使用 SPL RecursiveDirectoryIterator,程式碼更簡潔、健壯、符合 PSR 標準。若需模式匹配,glob() 是輕量好選擇。

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