2024 日本 PHP 研討會

DirectoryIterator::__construct

(PHP 5, PHP 7, PHP 8)

DirectoryIterator::__construct從路徑建構新的目錄迭代器

說明

public DirectoryIterator::__construct(字串 $directory)

從路徑建構新的目錄迭代器。

參數

directory

要遍歷的目錄路徑。

錯誤/例外

如果 directory 不存在,則拋出 UnexpectedValueException

如果 directory 是空字串,則拋出 ValueError

更新日誌

版本 說明
8.0.0 現在,如果 directory 為空字串,則會拋出 ValueError;先前它會拋出 RuntimeException

範例

範例 #1 DirectoryIterator::__construct() 範例

此範例將列出包含此腳本的目錄內容。

<?php
$dir
= new DirectoryIterator(dirname(__FILE__));
foreach (
$dir as $fileinfo) {
if (!
$fileinfo->isDot()) {
var_dump($fileinfo->getFilename());
}
}
?>

新增註記

使用者貢獻的註記 9 則註記

13
a dot lyskawa at nisza dot org
14 年前
這是多合一的 DirectoryIterator

<?php

/**
* Real Recursive Directory Iterator
*/
class RRDI extends RecursiveIteratorIterator {
/**
* Creates Real Recursive Directory Iterator
* @param string $path
* @param int $flags
* @return DirectoryIterator
*/
public function __construct($path, $flags = 0) {
parent::__construct(new RecursiveDirectoryIterator($path, $flags));
}
}

/**
* Real RecursiveDirectoryIterator Filtered Class
* Returns only those items which filenames match given regex
*/
class AdvancedDirectoryIterator extends FilterIterator {
/**
* Regex storage
* @var string
*/
private $regex;
/**
* Creates new AdvancedDirectoryIterator
* @param string $path, prefix with '-R ' for recursive, postfix with /[wildcards] for matching
* @param int $flags
* @return DirectoryIterator
*/
public function __construct($path, $flags = 0) {
if (
strpos($path, '-R ') === 0) { $recursive = true; $path = substr($path, 3); }
if (
preg_match('~/?([^/]*\*[^/]*)$~', $path, $matches)) { // matched wildcards in filename
$path = substr($path, 0, -strlen($matches[1]) - 1); // strip wildcards part from path
$this->regex = '~^' . str_replace('*', '.*', str_replace('.', '\.', $matches[1])) . '$~'; // convert wildcards to regex
if (!$path) $path = '.'; // if no path given, we assume CWD
}
parent::__construct($recursive ? new RRDI($path, $flags) : new DirectoryIterator($path));
}
/**
* Checks for regex in current filename, or matches all if no regex specified
* @return bool
*/
public function accept() { // FilterIterator method
return $this->regex === null ? true : preg_match($this->regex, $this->getInnerIterator()->getFilename());
}
}

?>

一些範例

<?php

/* @var $i DirectoryIterator */

foreach (new AdvancedDirectoryIterator('.') as $i) echo $i->getPathname() . '<br/>';
// 將輸出目前工作目錄中的所有檔案和目錄

foreach (new AdvancedDirectoryIterator('-R *.php') as $i) echo $i->getPathname() . '<br/>';
// 將輸出目前工作目錄和所有子目錄中的所有 php 檔案

foreach (new AdvancedDirectoryIterator('-R js/jquery-*.js') as $i) echo $i->getPathname() . '<br/>';
// 將輸出 js 目錄中的所有 jQuery 版本,如果 js 目錄不存在,則會拋出例外

?>

很酷吧? :)
10
kendsnyder at gmail dot com
16 年前
不要儲存 DirectoryIterator 物件以供稍後使用;當您儲存的物件數量超過作業系統限制(通常為 256 或 1024)時,您將收到「開啟的檔案過多」的錯誤。

例如,如果目錄中的檔案過多,則會產生錯誤

<?php
$files
= array();
foreach (new
DirectoryIterator('myDir') as $file) {
$files[] = $file;
}
?>

這種方法大概也很耗記憶體。
2
goran at extensionsforjoomla dot com
17 年前
我需要使用正規表達式在目錄樹中比對檔案名稱。程式碼基於 Marcus Börger 的 DirectoryTreeIterator 類別 http://cvs.php.net/viewvc.cgi/php-src/ext/spl/examples/ 以及他在 2007 年 PHP Quebec 研討會上關於物件導向 PHP 簡介的演講範例 http://talks.somabo.de/
<?php
class KeyFilter extends FilterIterator
{
private
$_rx;

function
__construct(Iterator $it, $regex)
{
parent::__construct($it);
$this->_rx= $regex;
}

function
accept()
{
return
ereg($this->_rx,$this->getInnerIterator()->key());
}

protected function
__clone() {
return
false;
}
}

class
DirMach extends KeyFilter
{
function
__construct($path , $regex)
{
parent::__construct(
new
DirectoryTreeIterator($path), $regex);
}

function
current()
{
return
parent::key();
}

function
key()
{
return
parent::key();
}
}

class
DirectoryTreeIterator extends RecursiveIteratorIterator
{
/** Construct from a path.
* @param $path directory to iterate
*/
function __construct($path)
{
try {
parent::__construct(
new
RecursiveCachingIterator(
new
RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::KEY_AS_FILENAME
),
CachingIterator::CALL_TOSTRING|CachingIterator::CATCH_GET_CHILD
),
parent::SELF_FIRST
);
} catch(
Exception $e) {
echo
$e->getMessage();
exit;
}
}

/** @return the current element prefixed with ASCII graphics
*/
function current()
{
if (
$this->hasChildren())
$this->next();
return
$this->key();
}

/** Aggregates the inner iterator
*/
function __call($func, $params)
{
return
call_user_func_array(array($this->getSubIterator(), $func), $params);
}
}
$PathToSearch = 'path_to_search';
$regex = 'regular_expression';
$FileList = new DirMach($PathToSearch, $regex);
foreach (
$FileList as $file) {
$match[] = $file;
}
echo
'<pre>';
var_dump($match);
echo
'</pre>';
?>
1
ahmad dot mayahi at gmail dot com
4 年前
許多開發者會混淆 DirectoryIterator 和 FilesystemIterator,以下列出它們之間的一些小差異

DirectoryIterator
* 路徑中包含 "." 和 ".."
* 數字鍵值。
* 值中不包含路徑。
* 無可用設定。
* 將元素儲存到陣列時,需要使用「clone」。

範例
<?php
$files
= [];
foreach (
$dir as $key => $item) {
echo
$key.PHP_EOL; // 鍵值是一個數字
$files[] = $item;
}

echo
$files[0]->getFilename(); // 這裡不會發生任何事,您需要在 foreach 迴圈內使用 clone $item

?>

FilesystemIterator
* 跳過點檔案。
* 路徑名稱同時用作鍵值和值。
* 可設定。
* 使用 SplFileInfo 儲存檔案。

「FilesystemIterator」是 DirectoryIterator 的增強版本,我更喜歡使用它而不是 DirectoryIterator。
0
h.man
3 年前
RecursiveDirectoryIterator 似乎會關閉目前開啟的檔案控制代碼。使用它之後,會出現「PHP 警告:fwrite():提供的資源不是有效的串流資源...」
0
cmanley at example dot com
5 年前
請注意,DirectoryIterator 在每次迭代中返回的是對自身的引用,而不是像人們一開始可能假設的那樣返回一個獨特的新的 SplFileInfo 物件。
如果您想將迭代結果推送到陣列中以便稍後處理,那麼了解這一點很重要。
如果您這樣做,則陣列中的所有項目都將是同一個 DirectoryIterator 物件,且具有相同的內部狀態(很可能無效 - 請參閱 valid() 方法),這可能不是您想要的。
因此,如果您確實想將迭代結果儲存在陣列中,則必須先將它們轉換為純字串或新的 SplFileInfo 物件。

$todo = [];
foreach (new DirectoryIterator('/some/dir') as $entry) {
if (!$entry->isFile()) {
continue;
}
#$todo []= $entry; # 不要這樣做!
$todo []= new SplFileInfo($entry->getFilename()); # 要這樣做!
#$todo []= $entry->getFilename(); # 或者如果您只對檔案名稱感興趣,可以這樣做。
}
0
pcdinh at phpvietnam dot net
17 年前
我需要遞迴遍歷目錄樹並取得所有子目錄路徑,並已編寫了一個程式碼片段來執行此操作。

<?php
$path
= "D:\webroot\phpvietnamcms";
foreach (new
RecursiveIteratorIterator(
new
RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::KEY_AS_PATHNAME), RecursiveIteratorIterator::CHILD_FIRST) as $file => $info) {
if (
$info->isDir())
{
echo
$file."<br />";
}
}

?>
0
springub at northclick dot de
17 年前
udvig dot ericson at gmail dot com
2006年7月29日 07:48

回應 udvig 以下的評論。該範例是錯誤的,以下是正確的範例

<?php
$dir
= new DirectoryIterator("/tmp");
foreach (
$dir as $file) {
if (
$file->isDot()) {
continue;
}
echo
$file->getFilename() . "\n";
}
?>
0
fernandobassani at gmail dot com
18 年前
我們現在可以用新的方法取代舊式的目錄內容列表方式!

舊式方法
<?php
if ($handle = opendir('/home/fernando/temp')) {
while (
false !== ($file = readdir($handle))) {
if (
$file != "." && $file != "..") {
print
"$file <br />";
}
}
closedir($handle);
}
?>

新式方法
<?php
$dir
= new DirectoryIterator('/home/fernando/temp');
while(
$dir->valid()) {
if(!
$dir->isDot()) {
print
$dir->current()."<br />";
}
$dir->next();
}
?>
To Top