rewinddir()
Узнайте, как rewinddir() в PHP сбрасывает внутренний указатель потока каталога в начало для повторного чтения без переоткрытия дескриптора.
При чтении каталога в PHP внутренний указатель отслеживает, насколько далеко вы продвинулись. Достигнув конца, указатель остаётся там — повторный вызов readdir() вернёт false без каких-либо записей. rewinddir() перемещает указатель обратно к первой записи, позволяя прочитать каталог во второй раз без его повторного открытия. На этой странице описано, что делает функция, её синтаксис, рабочий пример с несколькими проходами, типичные ловушки и случаи, когда стоит (и не стоит) её использовать.
Синтаксис
rewinddir(?resource $dir_handle = null): void$dir_handle— дескриптор каталога, ранее возвращённый функциейopendir(). Если параметр опущен, PHP использует дескриптор последнего вызоваopendir().- Возвращаемое значение —
rewinddir()возвращаетvoid(в более старых версиях PHP —null). Функция не сигнализирует об успехе или ошибке; при передаче недействительного дескриптора PHP генерируетTypeErrorили предупреждение.
Функция почти всегда используется совместно с opendir(), readdir() и closedir().
Как работает rewinddir()
Дескриптор каталога ведёт себя как курсор по записям каталога. readdir() продвигает этот курсор на одну запись за вызов и возвращает false, когда записи заканчиваются. rewinddir() просто перемещает курсор в начало, так что следующий вызов readdir() начнёт с первой записи.
Двойное чтение каталога
Это основной сценарий использования: перебрать каталог, а затем пройти по нему снова с того же дескриптора. Обратите внимание, что readdir($h) не возвращает записей при втором проходе до тех пор, пока не будет вызван rewinddir().
<?php
$h = opendir(__DIR__);
if ($h === false) {
die("Failed to open directory\n");
}
echo "First pass:\n";
while (($file = readdir($h)) !== false) {
echo " $file\n";
}
// Without rewinddir(), this loop would print nothing.
rewinddir($h);
echo "Second pass:\n";
while (($file = readdir($h)) !== false) {
echo " $file\n";
}
closedir($h);
?>Оба прохода выводят одинаковый набор записей (включая псевдо-директории . и .., которые readdir() всегда возвращает).
Распространённая ловушка: строгая проверка на false
Всегда сравнивайте результат readdir() с !== false, а не просто != или с помощью проверки на истинность. Каталог может законно содержать запись с именем "0", которое в PHP является ложным — при нестрогой проверке цикл завершится раньше времени, молча пропустив файлы.
<?php
// Wrong: stops as soon as it hits a file named "0" (or an empty name)
while ($file = readdir($h)) { /* ... */ }
// Correct: only stops at the genuine end of the stream
while (($file = readdir($h)) !== false) { /* ... */ }
?>Когда использовать rewinddir() — и когда не стоит
Используйте rewinddir(), когда вам нужен более одного прохода по одному и тому же открытому дескриптору, например, чтобы подсчитать итог на первом проходе (количество файлов, суммарный размер) и обработать каждую запись на втором. Это дешевле, чем вызывать closedir() и снова opendir(), поскольку позволяет избежать повторного открытия базового файлового дескриптора.
Если вам нужны записи только один раз или в отсортированном виде, предпочтите scandir(), который возвращает весь список в виде массива за один вызов — без необходимости управлять указателем. Обзор всех функций для работы с каталогами см. в главе PHP Directory.
Заключение
rewinddir() сбрасывает внутренний указатель потока каталога в начало, позволяя повторно прочитать каталог без лишних затрат на закрытие и повторное открытие дескриптора. В паре с opendir(), readdir() и closedir() она делает многопроходный обход каталога простым и эффективным. Используйте scandir() вместо неё, когда достаточно одного отсортированного списка.
graph TD
A[opendir] --> B[readdir]
B --> C{More items?}
C -->|Yes| B
C -->|No| D[rewinddir]
D --> B
B --> E[closedir]