DirectoryIterator::__construct

(PHP 5, PHP 7, PHP 8)

DirectoryIterator::__construct从路径构造新的目录迭代器

说明

public DirectoryIterator::__construct(string $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 备注

a dot lyskawa at nisza dot org
14 年前
这是一个一体化的 DirectoryIterator

<?php

/**
* 真正的递归目录迭代器
*/
class RRDI extends RecursiveIteratorIterator {
/**
* 创建真正的递归目录迭代器
* @param string $path
* @param int $flags
* @return DirectoryIterator
*/
public function __construct($path, $flags = 0) {
parent::__construct(new RecursiveDirectoryIterator($path, $flags));
}
}

/**
* 真正的递归目录迭代器过滤类
* 只返回文件名与给定正则表达式匹配的那些项目
*/
class AdvancedDirectoryIterator extends FilterIterator {
/**
* 正则表达式存储
* @var string
*/
private $regex;
/**
* 创建新的 AdvancedDirectoryIterator
* @param string $path, 以 '-R ' 为前缀表示递归,以 /[通配符] 为后缀表示匹配
* @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)) { // 在文件名中匹配通配符
$path = substr($path, 0, -strlen($matches[1]) - 1); // 从路径中剥离通配符部分
$this->regex = '~^' . str_replace('*', '.*', str_replace('.', '\.', $matches[1])) . '$~'; // 将通配符转换为正则表达式
if (!$path) $path = '.'; // 如果没有给出路径,我们假设为 CWD
}
parent::__construct($recursive ? new RRDI($path, $flags) : new DirectoryIterator($path));
}
/**
* 检查当前文件名中的正则表达式,如果没有指定正则表达式,则匹配所有内容
* @return bool
*/
public function accept() { // FilterIterator 方法
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/>';
// 将输出 CWD 中的所有文件和目录

foreach (new AdvancedDirectoryIterator('-R *.php') as $i) echo $i->getPathname() . '<br/>';
// 将输出 CWD 和所有子目录中的所有 php 文件

foreach (new AdvancedDirectoryIterator('-R js/jquery-*.js') as $i) echo $i->getPathname() . '<br/>';
// 将输出 js 目录中的所有 jQuery 版本,或者如果 js 目录不存在则抛出异常

?>

很酷,对吧?:)
kendsnyder at gmail dot com
15 年前
不要将 DirectoryIterator 对象存储起来以便稍后使用;如果您存储的文件超过操作系统限制(通常为 256 或 1024),您将收到一个错误,提示“打开的文件太多”。

例如,如果目录中的文件太多,这将导致错误

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

当然,这种方法也比较占内存。
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>';
?>
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。
h.man
3 年前
RecursiveDirectoryIterator 似乎会关闭当前打开的文件句柄。在使用它之后,会给出 "PHP Warning: fwrite(): supplied resource is not a valid stream resource in..." 错误...
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(); # 或者如果您只对文件名感兴趣,那就做这个。
}
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 />";
}
}

?>
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";
}
?>
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