closedir() 函数用于关闭由 opendir() 函数打开的目录句柄。
目录句柄在使用完毕后应该显式关闭,这是一个良好的编程习惯,特别是在处理大量目录句柄时,可以避免资源泄漏。
closedir(?resource $dir_handle = null): void
| 参数 | 描述 |
|---|---|
| dir_handle |
可选。由 如果省略此参数或设置为 从 PHP 8.0.0 开始,此参数可以为 null。 |
closedir() 函数没有返回值(返回 void)。
<?php
// 打开目录
$dir = "/tmp";
if ($handle = opendir($dir)) {
echo "目录打开成功: $dir<br>";
// 读取目录内容
echo "目录内容:<br>";
while (false !== ($entry = readdir($handle))) {
echo $entry . "<br>";
}
// 关闭目录句柄
closedir($handle);
echo "目录句柄已关闭";
} else {
echo "无法打开目录: $dir";
}
?>
<?php
// 打开第一个目录
$dir1 = "/tmp";
$handle1 = opendir($dir1);
if ($handle1) {
echo "第一个目录打开成功<br>";
// 读取一些内容
$firstEntry = readdir($handle1);
echo "第一个条目: $firstEntry<br>";
}
// 打开第二个目录
$dir2 = "/var/log";
$handle2 = opendir($dir2);
if ($handle2) {
echo "第二个目录打开成功<br>";
}
// 关闭最后打开的目录句柄(第二个)
closedir(); // 等同于 closedir($handle2)
echo "第二个目录句柄已关闭<br>";
// 关闭第一个目录句柄
closedir($handle1);
echo "第一个目录句柄已关闭";
?>
<?php
$dir = "/non/existent/directory";
$handle = null;
try {
// 尝试打开目录
$handle = @opendir($dir);
if (!$handle) {
throw new Exception("无法打开目录: $dir");
}
echo "目录打开成功<br>";
// 处理目录内容...
while (false !== ($entry = readdir($handle))) {
// 处理每个条目
echo $entry . "<br>";
}
} catch (Exception $e) {
echo "错误: " . $e->getMessage() . "<br>";
} finally {
// 确保目录句柄被关闭
if ($handle && is_resource($handle)) {
closedir($handle);
echo "目录句柄已确保关闭<br>";
}
}
?>
<?php
/**
* 递归列出目录中的所有文件和子目录
* @param string $path 要遍历的路径
*/
function listDirectory($path) {
if (!is_dir($path)) {
echo "$path 不是有效的目录<br>";
return;
}
// 打开目录
$handle = opendir($path);
if (!$handle) {
echo "无法打开目录: $path<br>";
return;
}
echo "<strong>目录: $path</strong><br>";
// 读取目录内容
while (false !== ($entry = readdir($handle))) {
// 跳过 . 和 ..
if ($entry == '.' || $entry == '..') {
continue;
}
$fullPath = $path . '/' . $entry;
// 如果是目录,递归调用
if (is_dir($fullPath)) {
echo "[目录] $entry/<br>";
// 注意:实际应用中可能需要深度限制
listDirectory($fullPath);
} else {
echo "[文件] $entry<br>";
}
}
// 关闭目录句柄
closedir($handle);
}
// 使用示例
listDirectory("/tmp");
?>
<?php
// 现代PHP推荐使用DirectoryIterator或FilesystemIterator
// 它们会自动管理资源,无需手动关闭
$dir = "/tmp";
echo "使用DirectoryIterator遍历目录:<br>";
$iterator = new DirectoryIterator($dir);
foreach ($iterator as $fileInfo) {
if ($fileInfo->isDot()) {
continue; // 跳过 . 和 ..
}
if ($fileInfo->isDir()) {
echo "[目录] " . $fileInfo->getFilename() . "/<br>";
} else {
echo "[文件] " . $fileInfo->getFilename() . "<br>";
}
}
// 不需要手动关闭,DirectoryIterator会自动清理
echo "遍历完成,资源已自动释放";
?>
| 错误 | 原因 | 解决方法 |
|---|---|---|
| Warning: closedir() expects parameter 1 to be resource, boolean given | opendir()失败返回false,但尝试关闭它 | 在调用closedir()之前检查句柄是否为有效资源 |
| Warning: closedir(): supplied argument is not a valid Directory resource | 尝试关闭已经关闭或无效的目录句柄 | 使用is_resource()检查句柄是否有效 |
| 资源泄漏 | 忘记关闭目录句柄 | 使用finally块或确保所有代码路径都调用closedir() |
| 特性 | opendir()/readdir()/closedir() | scandir() |
|---|---|---|
| 用法 | 需要手动打开、读取和关闭 | 一次性返回所有条目数组 |
| 内存使用 | 低(一次读取一个条目) | 高(一次性加载所有条目) |
| 控制粒度 | 高(可以提前停止遍历) | 低(必须处理整个数组) |
| 资源管理 | 需要手动管理 | 自动管理 |
| 适用场景 | 大型目录、需要提前中断的遍历 | 小型目录、简单遍历 |