What exactly are the benefits of using a PHP 5 DirectoryIterator

使用PHP 5 DirectoryIterator的好处是什么?

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

over a PHP 4 "opendir/readdir/closedir"

通过PHP 4“opendir / readdir / closedir”

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

besides the subclassing options that come with OOP?

除了OOP附带的子类选项?

4 个解决方案

#1


21

To understand the difference between the two, let's write two functions that read contents of a directory into an array - one using the procedural method and the other object oriented:

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

Procedural, using opendir/readdir/closedir

程序,使用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;
}

Object Oriented, using DirectoryIterator

面向对象,使用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;
}

Performance

Let's assess their performance first:

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

$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";

On my laptop (Win 7 / NTFS), procedural method seems to be clear winner:

在我的笔记本电脑(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)

On an entry-level AWS machine (CentOS):

在入门级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)

Above are results on PHP 5.4. You'll see similar results using PHP 5.3 and 5.2. Results are similar when PHP is running on Apache or NGINX.

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

Code Readability

Although slower, code using DirectoryIterator is more readable.

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

File reading order

The order of directory contents read using either method are exact same. That is, if list_directory_oo returns array('h', 'a', 'g'), list_directory_p also returns array('h', 'a', 'g')

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

Extensibility

Above two functions demonstrated performance and readability. Note that, if your code needs to do further operations, code using DirectoryIterator is more extensible.

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

e.g. In function list_directory_oo above, the $fileinfo object provides you with a bunch of methods such as getMTime(), getOwner(), isReadable() etc (return values of most of which are cached and do not require system calls).

例如在上面的函数list_directory_oo中,$ fileinfo对象为您提供了一堆方法,例如getMTim​​e(),getOwner(),isReadable()等(其中大多数的返回值都是缓存的,不需要系统调用)。

Therefore, depending on your use-case (that is, what you intend to do with each child element of the input directory), it's possible that code using DirectoryIterator performs as good or sometimes better than code using opendir.

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

You can modify the code of list_directory_oo and test it yourself.

您可以修改list_directory_oo的代码并自行测试。

Summary

Decision of which to use entirely depends on use-case.

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

If I were to write a cronjob in PHP which recursively scans a directory (and it's subdirectories) containing thousands of files and do certain operation on them, I would choose the procedural method.

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

But if my requirement is to write a sort of web-interface to display uploaded files (say in a CMS) and their metadata, I would choose DirectoryIterator.

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

You can choose based on your needs.

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

更多相关文章

  1. php吧字符串直接转换成数组处理
  2. PHP print_r 转换/还原为数组
  3. 本机PHP函数将授予我直接访问字符串部分而无需创建临时数组的权
  4. 快速使用数组的最近元素来确定新元素是否唯一
  5. 填充PHP数组:首先检查索引?
  6. PHP / Ajax:如何在成功登录后启动会话(剩余代码工作)
  7. 如何在php数组中获取php键值
  8. 将SQL查询的SELECT子句解析为PHP数组
  9. PHP不区分大小写数组搜索函数[duplicate]

随机推荐

  1. Android UI详解之动态布局
  2. android aidl通讯两个APP之间的应用
  3. android读写文件
  4. C# mono android 图片上传进度条实现
  5. android 2.2+ 完全退出程序的方法
  6. android SpannableString使用详解,替代多
  7. android中Search之Creating a Searchable
  8. Android(安卓)MediaPlayer研究问题
  9. 判断手机类型
  10. Linearlayout 添加divider