Rewinddir: примеры (PHP)
rewinddir(resource $dir_handle): voidФункция rewinddir в PHP сбрасывает указатель внутреннего итератора каталога на начало списка записей. Это означает, что последующий вызов readdir() начнет чтение заново с первой записи в директории.
Функция используется при работе с дескриптором каталога, открытого с помощью opendir(), когда требуется повторно пройти по списку файлов и поддиректорий без необходимости повторного открытия каталога.
Функция принимает один необязательный аргумент:
- $dir_handle (ресурс) — Дескриптор (resource) каталога, ранее открытый с помощью
opendir(). Если аргумент не указан, функция попытается использовать последний дескриптор каталога, использованный вopendir(). Однако такое поведение считается устаревшим и ненадежным. Начиная с PHP 8.0.0, этот параметр является обязательным.
Перемотка дескриптора каталога для повторного чтения.
<?php
$dir = opendir('.');
if ($dir) {
echo "Первое чтение:\n";
while (($file = readdir($dir)) !== false) {
echo $file . "\n";
}
rewinddir($dir); // Сброс указателя
echo "\nПовторное чтение:\n";
while (($file = readdir($dir)) !== false) {
echo $file . "\n";
}
closedir($dir);
}
?>Первое чтение: . .. index.php style.css Повторное чтение: . .. index.php style.css
<?php
$handle = opendir('/tmp');
rewinddir($handle); // В PHP 8 передача аргумента обязательна
// ... дальнейшие операции с readdir($handle)
closedir($handle);
?>- opendir() — Открывает дескриптор каталога. Это необходимая операция перед использованием
rewinddir(). - readdir() — Читает следующую запись из дескриптора каталога.
rewinddir()сбрасывает внутренний указатель этой функции. - scandir() — Сканирует указанную директорию и возвращает массив всех файлов и поддиректорий. Эта функция сама управляет указателем и возвращает полный список, поэтому
rewinddir()не требуется. Предпочтительнее для получения полного списка сразу в массив. - Функции итератора DirectoryIterator — Объектно-ориентированный интерфейс (например,
DirectoryIterator::rewind()), который обычно удобнее и безопаснее для итерации по каталогам.
Функцию rewinddir() предпочтительно использовать в низкоуровневом потоковом чтении больших директорий, где нецелесообразно хранить весь список в памяти (как это делает scandir()), и требуется несколько проходов по данным.
<?php
rewinddir('not_a_resource'); // Не ресурс
?>Warning: rewinddir() expects parameter 1 to be resource, string given
<?php
$dir = opendir('.');
closedir($dir);
rewinddir($dir); // Дескриптор уже закрыт
?>Warning: rewinddir(): supplied resource is not a valid Directory resource
<?php // PHP 8.0 и выше
$dir = opendir('.');
rewinddir(); // Без аргументов
?>Fatal error: Uncaught ArgumentCountError: rewinddir() expects exactly 1 argument, 0 given
<?php
rewinddir(); // Нет последнего использованного дескриптора
?>Warning: rewinddir(): %s is not a valid Directory resource
- PHP 8.0.0: Параметр
$dir_handleстал обязательным. Ранее он был необязательным, и функция использовала последний открытый каталог. - До PHP 8.0.0, если параметр не был передан, функция использовала последний ресурс каталога, открытый
opendir(). Это поведение было удалено для улучшения ясности и предотвращения ошибок.
Поиск всех файлов .txt, затем подсчет их общего количества.
<?php
$dirHandle = opendir('.');
$txtFiles = [];
if ($dirHandle) {
// Первый проход: сбор .txt файлов
while (($entry = readdir($dirHandle)) !== false) {
if (str_ends_with($entry, '.txt')) {
$txtFiles[] = $entry;
}
}
echo "Найдены файлы: " . implode(', ', $txtFiles) . "\n";
rewinddir($dirHandle);
$count = 0;
// Второй проход: просто подсчет всех записей
while (($entry = readdir($dirHandle)) !== false) {
$count++;
}
echo "Всего записей в директории: $count\n";
closedir($dirHandle);
}
?>Найдены файлы: readme.txt, notes.txt Всего записей в директории: 8
<?php
function customGlob($pattern, $path = '.') {
$dirHandle = opendir($path);
$matches = [];
if (!$dirHandle) return $matches;
// Преобразуем шаблон glob в регулярное выражение
$regex = '/^' . str_replace(['.', '*'], ['\.', '.*'], $pattern) . '$/';
while (($file = readdir($dirHandle)) !== false) {
if (preg_match($regex, $file)) {
$matches[] = $file;
}
}
closedir($dirHandle);
return $matches;
}
print_r(customGlob('*.php'));
?>Array
(
[0] => index.php
[1] => admin.php
)Использование rewinddir внутри вложенного цикла чтения может привести к неожиданным результатам.
<?php
$dir = opendir('.');
while (($file = readdir($dir)) !== false) {
if ($file == '..') continue;
echo "Внешний цикл: $file\n";
// Внутренний проход по тому же каталогу без открытия нового дескриптора
rewinddir($dir);
while (($innerFile = readdir($dir)) !== false) {
if ($innerFile == '..') continue;
echo " Внутренний: $innerFile\n";
break; // Важно иметь break, чтобы избежать бесконечного цикла
}
}
closedir($dir);
?>Внешний цикл: . Внутренний: . Внешний цикл: .. Внутренний: . Внешний цикл: index.php Внутренний: . ...
В Python для повторного чтения содержимого каталога обычно заново используют os.listdir() или вызывают seek(0) на объекте файлового дескриптора, возвращенного os.opendir().
import os
dir_handle = os.opendir('.')
# Первый проход
for entry in dir_handle:
print(entry.name)
# Возврат к началу с помощью seek
os.lseek(dir_handle.fileno(), 0, os.SEEK_SET)
# Или просто заново открыть итератор
dir_handle = os.opendir('.')
В Node.js используется асинхронный API. Повторное чтение директории обычно выполняется путем нового вызова fs.readdir() или fs.opendirSync() с последующим созданием нового итератора.
const fs = require('fs');
async function readDirTwice(path) {
const dir = await fs.promises.opendir(path);
// Первый проход
for await (const dirent of dir) {
console.log(dirent.name);
}
// Нет прямого аналога rewinddir, нужно открыть заново
const dir2 = await fs.promises.opendir(path);
for await (const dirent of dir2) { /* ... */ }
}Rewinddir в MySQL
В SQL нет прямой аналогии для работы с файловой системой сервера. Для списка файлов используются запросы к таблицам, например, INFORMATION_SCHEMA.FILES, и повторное выполнение запроса дает тот же эффект.