Работа с файлами через PHP: File API и примеры использования
Работа с файлами в PHP: File API
Наиболее эффективным способом для типовых операций с файлами (чтение и запись целиком) является использование функций file_get_contents и file_put_contents. Они автоматически открывают и закрывают файл, минимизируют код и обеспечивают хорошую производительность для небольших и средних файлов.
Пример чтения файла
$content = file_get_contents('example.txt');
echo $content;
Функция возвращает строку с содержимым файла или false при ошибке. Для получения содержимого в виде массива строк используйте file().
Пример записи в файл
$data = "Новая строка\n";
file_put_contents('example.txt', $data, FILE_APPEND); // добавление в конец
Третий параметр позволяет указать флаги: FILE_APPEND (дозапись), LOCK_EX (блокировка).
Типичные проблемы:
- Превышение лимита памяти при чтении большого файла – используйте потоковое чтение через fread.
- Отсутствие прав на запись – проверяйте is_writable() до операции.
Как читать файл построчно для обработки больших объёмов данных?
Используйте fopen и fgets для построчного чтения. Это позволяет не загружать весь файл в память.
$handle = fopen('large.log', 'r');
if ($handle) {
while (($line = fgets($handle)) !== false) {
echo $line;
}
fclose($handle);
}
Каждая итерация обрабатывает одну строку. После окончания файла feof() можно использовать для проверки.
Возможная ошибка: не учтён перевод строки в конце последней строки – используйте trim() при необходимости.
Как записать данные с блокировкой от одновременного доступа?
Функция flock позволяет установить исключительную блокировку на файл.
$handle = fopen('counter.txt', 'c'); // 'c' - создаёт файл, если его нет
if (flock($handle, LOCK_EX)) {
$count = (int) fread($handle, filesize('counter.txt'));
$count++;
ftruncate($handle, 0);
fwrite($handle, $count);
flock($handle, LOCK_UN);
}
fclose($handle);
Проблема: flock не работает на некоторых файловых системах (NFS) – альтернатива: использование базы данных.
Как работать с CSV-файлами (чтение и запись)?
Специализированные функции fgetcsv и fputcsv упрощают разбор строк с разделителями.
$handle = fopen('data.csv', 'r');
while (($row = fgetcsv($handle, 0, ',')) !== false) {
echo implode(' | ', $row) . "\n";
}
fclose($handle);
$data = [['Имя', 'Возраст'], ['Анна', 25], ['Иван', 30]];
$handle = fopen('output.csv', 'w');
foreach ($data as $row) {
fputcsv($handle, $row, ';');
}
fclose($handle);
Типичная ошибка: неверный разделитель или экранирование – проверяйте настройки локали.
Как загрузить файл на сервер через HTML-форму?
Используйте $_FILES и функцию move_uploaded_file.
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['file'])) {
$tmp = $_FILES['file']['tmp_name'];
$name = basename($_FILES['file']['name']);
$destination = __DIR__ . '/uploads/' . $name;
if (move_uploaded_file($tmp, $destination)) {
echo 'Файл загружен: ' . $destination;
} else {
echo 'Ошибка загрузки';
}
}
Проблемы: проверка типа файла по расширению ненадёжна – используйте mime_content_type или finfo.
Как удалить файл и проверить его существование?
unlink() удаляет файл, file_exists() проверяет наличие.
$file = 'temp.txt';
if (file_exists($file)) {
unlink($file);
echo 'Файл удалён';
} else {
echo 'Файла нет';
}
Ошибка: недостаточно прав – используйте is_writable().
Как читать удалённый файл по HTTP?
Обёртки потоков позволяют использовать file_get_contents с URL.
$content = file_get_contents('https://example.com/data.txt');
Для этого должна быть включена директива allow_url_fopen.
Если allow_url_fopen отключён, используйте cURL.
Расширенные примеры работы с файлами в PHP
Чтение большого файла с использованием буфера
При необходимости обработать файл гигабайтного размера без загрузки в память используется чтение блоками фиксированного размера.
$handle = fopen('bigfile.bin', 'rb');
$bufferSize = 4096; // 4KB
while (!feof($handle)) {
$chunk = fread($handle, $bufferSize);
// Обработка $chunk
}
fclose($handle);
Результат: каждый вызов fread возвращает до 4096 байт, что минимизирует потребление памяти.
Рекурсивное удаление каталога со всем содержимым
Стандартная функция rmdir удаляет только пустые каталоги. Для полного удаления требуется рекурсия.
function removeDirectory($dir) {
if (!is_dir($dir)) {
return;
}
$items = scandir($dir);
foreach ($items as $item) {
if ($item === '.' || $item === '..') continue;
$path = $dir . DIRECTORY_SEPARATOR . $item;
if (is_dir($path)) {
removeDirectory($path);
} else {
unlink($path);
}
}
rmdir($dir);
}
removeDirectory('/path/to/dir');
При успешном выполнении каталог и все его содержимое удаляются без возврата значения.
Проблема: возможна ошибка прав доступа – перед удалением проверяйте is_writable().
Использование SplFileObject для объектно-ориентированной работы с файлами
Класс SplFileObject предоставляет методы для итерации по строкам, получения CSV-данных и т.д.
$file = new SplFileObject('data.csv');
$file->setFlags(SplFileObject::READ_CSV | SplFileObject::SKIP_EMPTY);
foreach ($file as $row) {
print_r($row);
}
Результат: каждая итерация возвращает массив полей из CSV.
Генератор для чтения больших файлов
Генераторы позволяют элегантно обрабатывать строки файла без массива в памяти.
function readLines($filename) {
$handle = fopen($filename, 'r');
while (($line = fgets($handle)) !== false) {
yield $line;
}
fclose($handle);
}
foreach (readLines('huge.log') as $line) {
// Обработка строки
}
Каждый вызов yield приостанавливает выполнение функции, экономя память.
Работа с временными файлами через tmpfile
Функция tmpfile() создаёт временный файл, который автоматически удаляется после закрытия.
$temp = tmpfile();
fwrite($temp, 'Временные данные');
fseek($temp, 0); // для чтения
$content = fread($temp, 1024);
fclose($temp); // файл удаляется
Удобно для кеширования промежуточных результатов.
Использование потоковых оберток для сжатия (compress.zlib)
PHP позволяет читать и писать gzip-файлы напрямую через обёртку compress.zlib://.
$content = file_get_contents('compress.zlib://file.txt.gz');
echo $content;
Также можно открыть для записи:
$handle = fopen('compress.zlib://output.txt.gz', 'w');
fwrite($handle, 'Сжатые данные');
fclose($handle);
Результат: на диске создается gzip-архив, который можно распаковать стандартными утилитами.