PHP:scandir()太慢了

12

我需要编写一个列出文件夹中所有子文件夹的函数。我已经添加了不包含文件的过滤器,但是该函数使用scandir()进行列举,这使应用程序非常缓慢。有没有替代scandir()的函数,即使是非本地的php函数?


4
你正在扫描的目录中有多少个文件/目录?除非你在每个目录上执行stat(),或者里面有成千上万个文件,否则它不应该那么慢。 - Marc B
1
http://www.php.net/manual/en/function.scandir.php#96326 - Detect
1
http://www.php.net/manual/en/function.scandir.php#73062 - Detect
1
请查看PHP手册中的“示例#2 PHP 4替代scandir()”部分。 - Jeff Busby
2个回答

5
您可以使用readdir,它可能更快,类似这样的方式:
function readDirectory($Directory,$Recursive = true)
{
    if(is_dir($Directory) === false)
    {
        return false;
    }

    try
    {
        $Resource = opendir($Directory);
        $Found = array();

        while(false !== ($Item = readdir($Resource)))
        {
            if($Item == "." || $Item == "..")
            {
                continue;
            }

            if($Recursive === true && is_dir($Item))
            {
                $Found[] = readDirectory($Directory . $Item);
            }else
            {
                $Found[] = $Directory . $Item;
            }
        }
    }catch(Exception $e)
    {
        return false;
    }

    return $Found;
}

可能需要一些微调,但这基本上就是scandir所做的事情,如果不是,请写一个更新,因为我想看看是否能找到更快的解决方案。
另一个问题是,如果您读取一个非常大的目录,您正在填充内部存储器中的数组,这可能是您的内存消耗的原因。
您可以尝试创建一个函数来读取偏移量,以便您可以每次返回50个文件!
按块读取文件也同样简单易用,像这样:
$offset = 0;
while(false !== ($Batch = ReadFilesByOffset("/tmp",$offset)))
{
    //Use $batch here which contains 50 or less files!

    //Increment the offset:
    $offset += 50;
}

1
一切似乎都很完美,但如何禁用这些“.”和“..”文件夹呢?我还有一个空的索引,不想列出来。我猜是在catch(Exception)中,但如何格式化它呢? - Emil Avramov
1
我已经更新了代码,使其不包含 ...,但是关于空索引的问题,我不确定你的意思。 - RobertPitt

5
不要自己编写。PHP有一个专门用于此目的的递归目录迭代器:Recursive Directory Iterator。
通常来说(也就是不是100%的情况下),由于它是使用C语言实现的,所以在PHP中构建任何东西都会更慢。
链接:http://php.net/manual/en/class.recursivedirectoryiterator.php

2
除非你正在编写实时软件,否则 PHP 的“慢”根本不重要。 - dynamic
1
将目录迭代器包装在“ParentIterator”(或定制的迭代器过滤器)中,然后就没有文件了。 - salathe
在许多情况下,速度的缓慢都是很重要的。 - algo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接