gpt4 book ai didi

php - 与 PHP 4 "opendir/readdir/closedir"相比,使用 PHP 5 DirectoryIterator 到底有什么好处?

转载 作者:IT王子 更新时间:2023-10-29 00:07:20 25 4
gpt4 key购买 nike

使用 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返回 array( 'h', 'a', 'g')

可扩展性

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

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

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

可以修改list_directory_oo的代码,自己测试。

总结

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

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

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

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

关于php - 与 PHP 4 "opendir/readdir/closedir"相比,使用 PHP 5 DirectoryIterator 到底有什么好处?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17775848/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com