Работа с файлами в PHP
PHP предоставляет широкие возможности для работы с файлами и папками на сервере. В этой статье рассматриваются функции файловой системы PHP.
Работа с файлами — одна из самых распространённых задач в серверном программировании: запись логов, создание отчётов, кэширование данных, импорт CSV-файлов и организация загрузок — всё это завязано на файловую систему. PHP поставляется с богатым набором встроенных функций для работы с файлами, поэтому внешние библиотеки нужны крайне редко.
В этой главе рассматривается полный жизненный цикл файла — создание, чтение, обновление и удаление (CRUD) — и объясняется, когда использовать тот или иной подход. В целом PHP предлагает два стиля:
- Вспомогательные функции для работы с целым файлом (
file_get_contents(),file_put_contents()) — одна строка кода, идеально подходит для небольших файлов, которые целиком помещаются в памяти. - Потоковые функции (
fopen(),fread(),fwrite(),fgets(),fclose()) — предоставляют дескриптор, позволяющий читать или писать большой файл по частям, не загружая его целиком.
Умение выбрать правильный подход — разница между кодом, который работает с конфигурационным файлом размером 2 КБ, и кодом, который справится с логом размером 2 ГБ.
Режимы открытия файлов
Каждый потоковый вызов начинается с fopen($filename, $mode), и именно режим чаще всего вызывает затруднения у начинающих. Он определяет, открывается ли файл для чтения, записи или обоих операций, стирается ли существующее содержимое и где начинается внутренний указатель.
| Режим | Чтение | Запись | Указатель | Если файл отсутствует | Существующее содержимое |
|---|---|---|---|---|---|
"r" | да | нет | начало | предупреждение, возвращает false | сохраняется |
"r+" | да | да | начало | предупреждение, возвращает false | сохраняется |
"w" | нет | да | начало | создаётся | стирается (усекается) |
"w+" | да | да | начало | создаётся | стирается (усекается) |
"a" | нет | да | конец | создаётся | сохраняется (дописывается) |
"a+" | да | да | конец | создаётся | сохраняется (дописывается) |
"x" | нет | да | начало | создаётся | завершается ошибкой, если файл уже существует |
Добавьте "b" (например "rb", "wb") для безопасной работы с бинарными данными при работе с изображениями, PDF-файлами или любыми нетекстовыми данными — это предотвращает преобразование символов перевода строки в Windows.
Создание и запись файла
Чтобы создать файл, откройте его в режиме записи с помощью fopen() и запишите данные через fwrite(). Всегда закрывайте дескриптор с помощью fclose() по завершении работы — это сбрасывает буфер на диск и освобождает ресурс.
<?php
$file = fopen("test.txt", "w"); // create/truncate, open for writing
fwrite($file, "Hello World\n");
fwrite($file, "Second line\n"); // each call appends after the previous one
fclose($file); // flush to disk and release the handleОткрытие с режимом "w" стирает любое существующее содержимое. Чтобы добавить данные в файл, не уничтожая уже имеющиеся, откройте его в режиме дозаписи ("a"):
<?php
$log = fopen("app.log", "a"); // pointer starts at end of file
fwrite($log, "User logged in at " . date("H:i:s") . "\n");
fclose($log);Для быстрой однострочной записи, когда вся строка уже находится в памяти, пропустите дескриптор и используйте file_put_contents():
<?php
file_put_contents("test.txt", "Hello World\n"); // overwrite
file_put_contents("app.log", "another line\n", FILE_APPEND); // appendВсегда проверяйте возвращаемое значение
fopen(). Если путь неверен или директория недоступна для записи, функция вернётfalseи PHP выдаст предупреждение — использованиеfalseв качестве дескриптора приведёт к скрытой ошибке.
<?php
$file = fopen("/protected/test.txt", "w");
if ($file === false) {
die("Could not open the file for writing.");
}
fwrite($file, "data");
fclose($file);Чтение файла
Самый простой способ прочитать небольшой файл — file_get_contents(), которая возвращает всё содержимое в виде одной строки:
<?php
$content = file_get_contents("test.txt");
echo $content; // prints everything in the fileКогда файл большой, загружать его целиком в память неэффективно. Читайте его построчно с помощью fgets(), в цикле до достижения feof() (конца файла):
<?php
$file = fopen("test.txt", "r");
while (!feof($file)) {
$line = fgets($file); // reads one line, including the newline
echo $line;
}
fclose($file);Если нужно получить каждую строку как элемент массива за один вызов, удобна функция file() — однако, как и file_get_contents(), она загружает весь файл в память:
<?php
$lines = file("test.txt"); // array, one element per line
echo "This file has " . count($lines) . " lines.";Хорошей практикой является проверка существования файла перед его чтением с помощью file_exists() (или is_readable() для проверки прав доступа):
<?php
if (file_exists("test.txt")) {
echo file_get_contents("test.txt");
} else {
echo "File not found.";
}Обновление файла
Для замены содержимого файла наиболее удобный инструмент — file_put_contents(). Она открывает, записывает и закрывает файл за один вызов:
<?php
$content = "Hello World Again\n";
file_put_contents("test.txt", $content); // replaces the old contentsЧтобы добавить данные в файл, а не заменить их, передайте флаг FILE_APPEND (показано выше) или откройте файл в режиме дозаписи через fopen(). Функции «изменить строку 3» не существует — для изменения части файла обычно читают его, модифицируют данные в PHP и записывают обратно.
Удаление файла
Используйте unlink() — обратите внимание на нестандартное название — для удаления файла. Функция возвращает true при успехе и false при неудаче, поэтому используйте её совместно с file_exists(), чтобы избежать предупреждения:
<?php
if (file_exists("test.txt")) {
if (unlink("test.txt")) {
echo "File deleted.";
} else {
echo "Could not delete the file.";
}
} else {
echo "Nothing to delete.";
}unlink() удаляет только файлы. Для удаления пустой директории используйте rmdir(); смотрите раздел Директории PHP для работы с папками.
Когда использовать тот или иной подход
- Небольшие текстовые или конфигурационные файлы, содержимое целиком →
file_get_contents()/file_put_contents(). - Большие файлы, построчное чтение →
fopen()+fgets()/fread(). - Дозапись в лог → режим
"a"илиFILE_APPEND. - Создание файла только если он ещё не существует → режим
"x". - Бинарные данные (изображения, PDF) → добавьте флаг
"b"и используйтеfread()/fwrite().
Итоги
Работа с файлами — ключевая часть серверного PHP. Вы познакомились с двумя семействами функций — однострочными вспомогательными функциями для работы с целым файлом и потоковыми функциями с дескрипторами — и узнали, когда каждое из них уместно, как режимы управляют усечением и дозаписью, как эффективно читать большие файлы с помощью fgets()/feof(), а также как обновлять и безопасно удалять файлы.
Для более глубокого изучения загляните в специализированные главы: Создание и запись файла, Открытие и чтение файла, Функции файловой системы PHP, Загрузка файлов и Директории PHP.