PHP: scandir() работает слишком медленно

Я должен сделать функцию, которая перечисляет все подпапки в папку. У меня есть фильтр без файлов, но функция использует scandir() для вывода списка. Это делает приложение очень медленным. Есть ли альтернатива scandir(), даже не родная функция php? Заранее спасибо!


person Emil Avramov    schedule 02.03.2011    source источник
comment
Сколько файлов/каталогов находится в каталоге, который вы сканируете? Это не должно быть НАСТОЛЬКО медленным, если только вы не выполняете stat() для каждого каталога по мере его появления или там тысячи файлов.   -  person Marc B    schedule 02.03.2011
comment
взгляните на руководство по php в Примере № 2 Альтернативы PHP 4 для scandir()   -  person Jeff Busby    schedule 02.03.2011


Ответы (2)


Вы можете использовать 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;
}
person RobertPitt    schedule 02.03.2011
comment
вроде все отлично, но как это отключить. и .. папки. У меня также есть пустой индекс, который я не хочу перечислять. Я предполагаю, что это в улове (исключение), но как его отформатировать? - person Emil Avramov; 03.03.2011
comment
Я обновил так, чтобы он не содержал . или .., но я не уверен, что вы имеете в виду в отношении пустого индекса - person RobertPitt; 03.03.2011

Не пишите свои. PHP имеет рекурсивный итератор каталогов, созданный специально для этого:

http://php.net/manual/en/class.recursivedirectoryiterator.php

Как правило (то есть не в 100% случаев), поскольку он реализован на чистом C, все, что вы создаете на PHP, будет работать медленнее.

person CaseySoftware    schedule 02.03.2011
comment
Если вы не пишете программное обеспечение в реальном времени, медлительность php вообще не имеет значения. - person dynamic; 03.03.2011
comment
Оберните итератор каталога в ParentIterator (или специальный фильтр итератора) и бац, никаких файлов. - person salathe; 06.03.2011