相对于 PHP 4“opendir/readdir/closedir”,使用 PHP 5 DirectoryIterator 到底有什么好处?

2024-02-01

使用 PHP 5 DirectoryIterator 到底有什么好处

$dir = new DirectoryIterator(dirname(__FILE__));
foreach ($dir as $fileinfo) 
{
    // handle what has been found
}

通过 PHP 4“opendir/readdir/closedir”

if($handle = opendir(dirname(__FILE__))) 
{
    while (false !== ($file = readdir($handle))) 
    {
        // handle what has been found
    }
    closedir($handle);
}

除了 OOP 附带的子类化选项之外?


为了理解两者之间的区别,让我们编写两个将目录内容读取到数组中的函数 - 一个使用过程方法,另一个使用面向对象的方法:

程序化,使用 opendir/readdir/closedir

function list_directory_p($dirpath) {
    if (!is_dir($dirpath) || !is_readable($dirpath)) {
        error_log(__FUNCTION__ . ": Argument should be a path to valid, readable directory (" . var_export($dirpath, true) . " provided)");
        return null;
    }
    $paths = array();
    $dir = realpath($dirpath);
    $dh = opendir($dir);
    while (false !== ($f = readdir($dh))) {
        if ("$f" != '.' && "$f" != '..') {
            $paths[] = "$dir" . DIRECTORY_SEPARATOR . "$f";
        }
    }
    closedir($dh);
    return $paths;
}

面向对象,使用 DirectoryIterator

function list_directory_oo($dirpath) {
    if (!is_dir($dirpath) || !is_readable($dirpath)) {
        error_log(__FUNCTION__ . ": Argument should be a path to valid, readable directory (" . var_export($dirpath, true) . " provided)");
        return null;
    }
    $paths = array();
    $dir = realpath($dirpath);
    $di = new DirectoryIterator($dir);
    foreach ($di as $fileinfo) {
        if (!$fileinfo->isDot()) {
            $paths[] = $fileinfo->getRealPath();
        }
    }
    return $paths;
}

表现

我们先评估一下他们​​的表现:

$start_t = microtime(true);
for ($i = 0; $i < $num_iterations; $i++) {
    $paths = list_directory_oo(".");
}
$end_t = microtime(true);
$time_diff_micro = (($end_t - $start_t) * 1000000) / $num_iterations;
echo "Time taken per call (list_directory_oo) = " . round($time_diff_micro / 1000, 2) . "ms (" . count($paths) . " files)\n";

$start_t = microtime(true);
for ($i = 0; $i < $num_iterations; $i++) {
    $paths = list_directory_p(".");
}
$end_t = microtime(true);
$time_diff_micro = (($end_t - $start_t) * 1000000) / $num_iterations;
echo "Time taken per call (list_directory_p) = " . round($time_diff_micro / 1000, 2) . "ms (" . count($paths) . " files)\n";

在我的笔记本电脑(Win 7 / NTFS)上,程序方法似乎是明显的赢家:

C:\code>"C:\Program Files (x86)\PHP\php.exe" list_directory.php
Time taken per call (list_directory_oo) = 4.46ms (161 files)
Time taken per call (list_directory_p) = 0.34ms (161 files)

在入门级 AWS 计算机 (CentOS) 上:

[~]$ php list_directory.php
Time taken per call (list_directory_oo) = 0.84ms (203 files)
Time taken per call (list_directory_p) = 0.36ms (203 files)

以上是 PHP 5.4 上的结果。使用 PHP 5.3 和 5.2 您将看到类似的结果。当 PHP 在 Apache 或 NGINX 上运行时,结果类似。

代码可读性

虽然速度较慢,但​​代码使用DirectoryIterator更具可读性。

文件读取顺序

使用任一方法读取目录内容的顺序完全相同。也就是说,如果list_directory_oo回报array('h', 'a', 'g'), list_directory_p also returns array('h', 'a', 'g')

可扩展性

以上两个函数展示了性能和可读性。请注意,如果您的代码需要执行进一步的操作,请使用代码DirectoryIterator更具可扩展性。

例如功能中list_directory_oo上面,$fileinfo对象为您提供了很多方法,例如getMTime(), getOwner(), isReadable()等(其中大部分的返回值被缓存并执行not需要系统调用)。

因此,根据您的用例(即您打算对输入目录的每个子元素执行的操作),代码可能使用DirectoryIterator与使用的代码一样好,有时甚至更好opendir.

您可以修改以下代码list_directory_oo并亲自测试一下。

Summary

使用哪个的决定完全取决于用例。

如果我用 PHP 编写一个 cronjob,它递归地扫描包含数千个文件的目录(及其子目录)并对它们执行某些操作,我会选择过程方法。

但如果我的要求是编写一种 Web 界面来显示上传的文件(例如在 CMS 中)及其元数据,我会选择DirectoryIterator.

您可以根据您的需要进行选择。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

相对于 PHP 4“opendir/readdir/closedir”,使用 PHP 5 DirectoryIterator 到底有什么好处? 的相关文章

随机推荐

  • 聚集索引列上的非聚集索引可以提高性能吗?

    在SQL Server 2005中 查询分析器多次告诉我在已经有聚集索引的表的主ID列上创建非聚集索引 遵循此建议后 查询执行计划报告查询应该更快 为什么同一列 具有相同排序顺序 上的非聚集索引比聚集索引更快 聚集索引包含表的所有数据 而非
  • 探测扩展时出现 GET net::ERR_FAILED 错误

    有一个特定的 Chrome 扩展程序 我想从中获取一个 PNG 文件XMLHttpRequest 如果启用了扩展 我想将 load 写入控制台 如果禁用扩展 我想将 error 写入控制台 它工作正常 但如果禁用扩展程序 Chrome 会在
  • 列出 GCP 帐户/组织的所有用户

    我在 GCP 中有一个组织 其中有多个项目 有没有办法列出所有项目用户及其角色 而不必逐个项目访问项目 我正在使用gcloud projects get iam policy PROJECTNAME 但列出单个项目的用户 我有几百个 Tha
  • Javascript:无法将 href 添加到列表项

    我正在尝试将新项目添加到列表项目中 但下面的代码没有将超链接添加到我想要的列表项 有人可以告诉我出了什么问题吗 HTML div ul li Ut enim ad minim veniam li li Excepteur sint occa
  • “Angular cdk Drag drop”用于将列表中的项目拖放到容器中(无序)

    我知道 cdk 拖放可以很好地处理列表 并且有很多示例 但我想做的是 一侧是列表 另一侧是容器 容器中的物品应该位于容器中的任何位置 并且可以由 x 和 y 轴固定 因此 当从列表中拖放到容器中的某个 x y 处时 该项目应保持该位置 请帮
  • ASP MVC5 身份用户抽象

    我想使用默认的 Identity 2 提供程序构建 N 轮胎 Web 应用程序 因此 我的数据层包含带有模型定义的纯 C 类 没有任何外部依赖性 但如果不添加 AspNet Identity 引用 就不可能将某些类链接到我的应用程序用户 我
  • 如何获取 iOS 框架测试目标并在虚拟应用程序中运行它?

    所以我遇到了一个问题 我的框架需要访问KeyChain 很好 但是在模拟器中运行时似乎失败了 挖掘它似乎是一个已知的问题xctest在这里做错事了 公平地说 错误是会发生的 在 Apple 开发者论坛中 对此进行了讨论 Right 这是库测
  • 验证两个表的唯一性

    我有一个Company and Archive具有相同表结构的模型 两种型号都有一个validates name uniqueness gt true验证 在 company rb 文件中 我在设置自定义验证时遇到问题 当我将记录添加到Co
  • Ruby 的 Object#taint 和 Object#trust 方法是什么?

    我正在阅读有关 Ruby 字符串方法的内容docs http www ruby doc org core 1 9 3 String html并遇到了这些方法 taint trust untaint untrust 我不知道它们是做什么的 我
  • BottomNavigationView:如何删除连字符标签

    实现 5 项 BottomNavigationView 始终显示标签 我使用以下方法
  • 如何在 extjs 中的网格页脚中添加总行数

    我想在网格页脚中添加总行数 我有商店中可用的总行记录 在网格中 用户选择降序排列 总计行显示为第一行 谁能告诉我如何避免这种情况 我将解释我的完整问题 例如 我有像 Target Target1 Target2 这样的网格视图 是从网络服务
  • Integer.parseInt(string) 实际上是如何工作的?

    最近被问到这个问题 不知道答案 有人可以从高层次解释Java如何获取字符 字符串并将其转换为int 通常这是这样完成的 初始化结果为 0 for each character in string do this 结果 结果 10 从字符中获
  • 如何用笛卡尔绘制波纹圆?

    I m looking for a way to plot a corrugated circle https www mypandakitchen com 1656 large default emporte pieces rond on
  • 扩展界面生成器中的属性检查器

    是否可以使用继承自 UIView 的自定义类的附加属性来扩展界面构建器的属性检查器 现在不行 Interface Builder 允许您通过 Interface Builder 插件为您的对象实现自定义检查器 不过 IB Kit 目前不支持
  • 如何从 ipython 启动twisted的reactor

    我需要从 ipython 中启动一个twisted reactor 以允许继续交互 Ipython 的手册页引用了twisted 但我无法理解应该如何继续 文档引用了 IPython kernel twistedutil 所以我的印象是它应
  • 在 ASP.NET core 中添加迁移时不考虑新的更改

    我和一个朋友正在作为队友参与 ASP NET Core 项目并使用以下工具共享数据github 每次从 who 中提取更改时github 应该删除Migration folder为了添加迁移而不会出现任何错误 否则 我们会收到以下错误 数据
  • 寻找第 N 个孪生素数

    我试图解决 SPOJ 上的问题 我们需要计算第 n 个孪生素数对 相差 2 的素数 n 可以大到 10 5 我尝试使用筛子进行预先计算 我必须筛选最多 10 8 才能获得最大的 n 个孪生素数 但时间限制很严格 2s 并且超时 我注意到人们
  • Visual Studio 2012 中数据库优先实体框架模型的 MVC4 支架

    我在使用 Visual Studio 2012 时遇到问题 尝试添加带有脚手架的 MVC4 控制器 理想情况下 我希望在与我的 Web 应用程序分开的程序集中使用添加新项 ADO NET 实体数据模型 即不是代码优先 从数据库生成实体框架模
  • 如何提示 Google Smart Lock 使用特定输入字段作为网站中的用户名

    我一直在尝试搜索一些有关如何提示 Chrome 的 Google Smart Lock 使用特定输入字段作为与用户名关联的输入字段的文档 但没有任何运气 对于密码 它与使用的一样完美type password 但是 当涉及多字段表单中的用户
  • 相对于 PHP 4“opendir/readdir/closedir”,使用 PHP 5 DirectoryIterator 到底有什么好处?

    使用 PHP 5 DirectoryIterator 到底有什么好处 dir new DirectoryIterator dirname FILE foreach dir as fileinfo handle what has been f