- PHP: список файлов и директорий
- Базовые решения
- Использование glob()
- Используем opendir() , readdir() , и closedir() .
- Использование scandir()
- Воспользуемся итераторами SPL
- FilesystemIterator
- Работа с файлами и директориями в PHP
- Полезные функции
- Работа с потоком
- Прямая работа с файлами
- Управление файлами
- Работа с директориями
- Загрузка файлов на сервер
PHP: список файлов и директорий
В данном уроке мы разберемся с типовой задачей, которая возникает во время работы над проектом PHP: получение списка файлов и директорий. Обсудим несколько базовых и более изощренных подходов, с перечисление плюсов и минусов каждого. Первые три решения будут использовать типовые функции PHP, а затем представим более надежное с применением итераторов SPL.
Для предметного обсуждения решения и демонстраций предположим, что структура директорий имеет следующий вид:
\---manager | \---user | \---document.txt | \---data.dat | \---style.css |---article.txt |---master.dat |---script.php |---test.dat |---text.txt
Базовые решения
Первый набор решений основан на использовании функции glob() , комбинации функций opendir() , readdir() и closedir() , и также функции scandir() .
Использование glob()
Первое решение базируется на использовании функции glob(), которая позволяет выполнять поиск пути с помощью шаблонов. Функция имеет два параметра:
- $pattern (обязательный): шаблон поиска
- $flags (опциональный): один или несколько флагов, описание которых можно найти в документации
Рассмотрим примеры. Для поиска в директории всех файлов и директорий, имена которых заканчиваются на .txt, следует использовать код:
Если вывести переменную $filelist , то получим:
array ( 0 => 'article.txt', 1 => 'text.txt' )
Если нужен список файлов и директорий, имена которых начинаются на “te”, то код будет выглядеть так:
array ( 0 => 'test.dat', 1 => 'text.txt' )
А для получения списка только директорий с именами, содержащих “ma”, используем код:
Обратите внимание, что в последнем примере использован флаг GLOB_ONLYDIR в качестве второго параметра функции. Поэтому файл master.dat исключен из списка. Хотя функция glob() очень проста в использовании, иногда она недостаточно гибкая. Например, нет флага для получения только файлов (без директорий), которые соответствуют шаблону.
Используем opendir() , readdir() , и closedir() .
Второй подход к получению списка файлов и директорий, который мы обсудим, заключается в использовании функций opendir() , readdir() , и closedir() .
Функция opendir() открывает директорию и возвращает дескриптор соединения. Как только дескриптор получен, можно использовать функцию readdir() . С каждым обращением данная функция выдает имя следующего файла или директории внутри открытого каталога. Если все имена уже были перечислены, функция возвращает false. Для закрытия дескриптора используется функция closedir() .
В отличие от использования функции glob() , данный подход сложнее, так как у вас нет параметров, которые помогают фильтровать список возвращаемых имен файлов и директорий. Вы должны выполнить фильтрацию самостоятельно, чтобы получить нужный результат.
Ниже приведенный пример возвращает список имен файлов и директорий начинающихся на “te”:
При выполнении выше приведенного кода, переменная $entry будет содержать такие включения, как “.” и “..”. Это две виртуальные директории, которые имеются в каждом каталоге файловой системы. Они представляют текущий каталог и родительский каталог соответственно.
Второй пример выводит только файлы, содержащиеся в заданном каталоге.
array ( 0 => 'article.txt', 1 => 'master.dat', 2 => 'script.php', 3 => 'test.dat', 4 => 'text.txt' )
Использование scandir()
В завершение представим функцию scandir() . Она имеет только один обязательный параметр: путь для чтения. Функция возвращает массив файлов и директорий, расположенных по указанному пути. Для получения списка файлов и директорий по определенному критерию нужно выполнить дополнительную фильтрацию. С другой стороны, решение получается более кратким и не требует управления дескрипторами.
Данный пример показывает, как получить список файлов и каталогов, имена которых начинаются на “te”:
Воспользуемся итераторами SPL
Теперь рассмотрим использование итераторов SPL. Но прежде, чем приступить к решению нашей задачи, проведем введение в библиотеку SPL и итераторы. Библиотека SPL предоставляет серию классов для объектно ориентированных структур данных, итераторов, дескрипторов файлов и прочее.
Одно из преимуществ итераторов заключается в том, что они являются классами и их можно расширить для удовлетворения собственных нужд. Другой плюс состоит в том, что итераторы имеют собственные методы, которые являются полезными при решении множества типовых задач и располагаются в одном месте. Посмотрите на пример использования FilesystemIterator в сравнении с readdir() . Оба метода применяют цикл, но в случае readdir() вы обрабатываете только строку, а FilesystemIterator работает с объектом, который может содержать дополнительную информацию о файле или директории (размер, владелец, права доступа и так далее).
Конечно, PHP представляет возможность для получения такой информации с помощью функций,например filesize() и fileowner(). Но PHP5 основан на использовании концепции ООП. Поэтому лучше использовать современные методы работы с языком программирования. На нашем сайте есть уроки, посвященные работе с итераторами.
Как уже сообщалось во водной части урока, мы рассмотрим использование FilesystemIterator , RecursiveDirectoryIterator и GlobIterator . Первый наследуется от DirectoryIterator , а остальные от FilesystemIterator . Они все имеют один и тот же конструктор, который принимает два параметра:
- $path (обязательный): путь к пункту файловой системы, над которым совершаются операции
- $flags (опциональный): один или несколько флагов, перечисленных в документации
Реальное различие в данных итераторах заключается в их использовании для навигации по заданному пути.
FilesystemIterator
Использовать FilesystemIterator очень просто. Рассмотрим в действии. Представляем два примера. Первый показывает поиск всех файлов и каталогов, имена которых начинаются на “te”. Второй пример использует другой итератор RegexIterator для поиска всех файлов и каталогов, имена которых заканчиваются на “t.dat” или “t.php”. Итератор RegexIterator используется для фильтрации результата на основе регулярных выражений.
getFilename(), "te") === 0) < $filelist[] = $entry->getFilename(); > >
Выше приведенный код выдаст результат, аналогичный предыдущим примерам.
Второй пример с применением RegexIterator :
Работа с файлами и директориями в PHP
PHP позволяет работать с файлами и каталогами. В данной заметке кратко о файловой системе, разберём основные функции для работы с файлами (открытие, запись, чтение) и директориями, хранящимися на веб-сервере.
Полезные функции
// Проверка файлов и директорий на существование if( file_exists("file.txt") ) < echo "Файл или директория существует"; >// Проверка файлов на существование if( is_file("file.txt") ) < echo "Файл существует"; >// Проверка директорий на существование if( is_dir("images") ) < echo "Директория существует"; >// Размер файла echo "Длина файла file.txt: " .filesize("file.txt"); // Время изменения и доступа к файлу echo "Файл file.txt был изменён: " . filemtime("file.txt"); echo "и запрошен: " . fileatime("file.txt"); // Что можно с файлом делать? if( is_readable("file.txt") ) < echo "Файл можно читать"; >if( is_writable("file.txt") ) < echo "В файл можно писать"; >if( is_executable("file.exe") )
Работа с потоком
// Открытие потока на чтение и получение его дескриптора $f = fopen("file.txt", "r") or die("Не могу открыть файл!"); // Закрытие потока fclose($f); // Открытие потока на чтение и запись $f = fopen("file.txt", "r+"); // Открытие потока на запись. Указатель помещается в конец файла $f = fopen("file.txt", "a"); // Открытие потока на чтение и запись. Указатель помещается в конец файла $f = fopen("file.txt", "a+"); // Открытие потока на запись. Файл обрезается до нулевой длины $f = fopen("file.txt", "w"); // Открытие потока на чтение и запись. Файл обрезается до нулевой длины $f = fopen("file.txt", "w+"); // Читаем файл кусками $f = fopen("file.txt", "r"); // Читаем первые 5 байт из потока echo fread($f, 5); // Читаем следующие 3 байта из потока echo fread($f, 3); //Выводим всё с текущей позиции до конца fpassthru($f); fclose($f); // Читаем файл построчно в массив $f = fopen("file.txt", "r"); $lines = []; while ( $line = fgets($f) ) < $lines[] = $line; >fclose($f); // Читаем файл построчно в массивы, вырезаем html-тэги, оставляя нужные $f = fopen("file.html", "r"); $lines = []; while ( $line = fgetss($f, 4096, "
") ) < $lines[] = $line; >fclose($f); // Читаем файл побайтово в массив $f = fopen("file.txt", "r"); $bytes = []; while ( !feof($f) ) < $bytes[]= fgetc($f); >fclose($f); // Пишем в файл $f = fopen("file.txt", "r+"); fwrite($f, "Новый текст", 25); fclose($f); // Пишем в конец файла $f = fopen("file.txt", "a"); fputs($f, "\nНовая строка"); fclose($f); // Читаем последние 10 байт из потока $f = fopen("file.txt", "r"); // Устанавливаем указатель в нужную позицию fseek($f, -10, SEEK_END); // В какой позиции мы находимся? echo ftell($f); // Читаем данные echo fread($f, 10); // Устанавливаем указатель в начало потока rewind($f); fclose($f);
Прямая работа с файлами
// Читаем весь файл напрямую в буфер вывода readfile("file.txt"); // Что и $f = fopen("file.txt", "r"); echo fread($f, filesize("file.txt")); fclose($f); // Читаем файл построчно в массив $lines = file("file.txt");; // Что и $f = fopen("file.txt", "r"); while ( $lines[] = fgets($f) ); fclose($f); // Получаем весь файл в виде строки $file = file_get_contents("file.txt"); // Что и $f = fopen("file.txt", "r"); $file = fread($f, filesize("file.txt")); fclose($f); // Пишем в файл затирая содержимое file_put_contents("file.txt", "Новое содержимое"); // Что и $f = fopen("file.txt", "w"); fputs($f, "Новое содержимое"); fclose($f); // Пишем в файл добавляя содержимое в конец file_put_contents("file.txt", "Новое содержимое", FILE_APPEND); // Что и $f = fopen("file.txt", "a"); fputs($f, "Новое содержимое"); fclose($f);
Управление файлами
// Копируем файл copy("source.txt", "destination.txt"); // Переименовываем файл rename("old.txt", "new.txt"); // Удаляем файл unlink("file-to-delete.txt");
Работа с директориями
// Создание директории mkdir("newdir"); // Удаление директории rmdir("dir-to-delete"); // Имя текущей директории echo getcwd(); // Заходим в текущую директорию $dir = opendir("."); // Читаем содержимое директории while ( $name = readdir($dir) )< if(is_dir($name)) echo '[' . $name . ']
'; else echo $name . '
'; > //Выходим из директории closedir($dir); // Читаем содержимое директории в массив $dir_content = scandir("."); // Читаем определённое содержимое директории в массив $dir_txt_content = glob("*.txt");