Сохранение информации в файл средствами PHP
Запись данных в файл в PHP: основные подходы
В PHP существует несколько способов записи информации в файлы. Выбор метода зависит от задачи: требуется ли дописать данные, создать новый файл или перезаписать существующий, нужна ли блокировка. В этом разделе рассматриваются основные функции и их применение.
Основное решение: file_put_contents
Как записать строку в файл одной командой без ручного открытия и закрытия?
Функция file_put_contents - наиболее простой способ записи данных в файл. Она открывает файл, записывает содержимое и закрывает его автоматически. Поддерживает флаги FILE_APPEND, LOCK_EX и др.
// Записать строку в файл (перезаписать)
$result = file_put_contents('example.txt', 'Hello, world!');
echo $result; // количество записанных байт
13
Типичная проблема:
Файл не записывается, если отсутствуют права на запись. Решение: проверить права на папку и файл, использовать is_writable().
if (!is_writable('example.txt')) {
exit('Нет прав на запись');
}
file_put_contents('example.txt', 'data');
Как использовать fwrite для точного контроля процесса записи?
Функции fopen / fwrite / fclose дают гибкость: можно открыть файл в нужном режиме, записывать данные по частям и выполнять дополнительные операции (например, блокировку).
$fp = fopen('log.txt', 'a'); // открыть для дописывания
if ($fp) {
fwrite($fp, 'Строка 1' . PHP_EOL);
fwrite($fp, 'Строка 2' . PHP_EOL);
fclose($fp);
}
Типичные ошибки:
- Забыли закрыть файл (
fclose) - ресурс остаётся занятым. - Использование неподходящего режима (
wвместоaприводит к удалению содержимого).
Как записать данные в начало файла без перезаписи остального содержимого?
Стандартные функции не позволяют вставить данные в начало файла напрямую. Можно прочитать файл, изменить строку и записать заново.
$file = 'data.txt';
$content = file_get_contents($file);
$newContent = 'Новая строка в начале' . PHP_EOL . $content;
file_put_contents($file, $newContent);
Проблема:
Для больших файлов такой подход потребляет много памяти. Альтернатива - использование временного файла или записи в конец с последующей сортировкой.
Как записать данные с блокировкой, чтобы исключить одновременную запись из нескольких процессов?
Блокировка реализуется с помощью flock или флага LOCK_EX в file_put_contents.
$fp = fopen('counter.txt', 'a');
if (flock($fp, LOCK_EX)) { // эксклюзивная блокировка
fwrite($fp, '1' . PHP_EOL);
flock($fp, LOCK_UN); // снять блокировку
}
fclose($fp);
Ошибки:
Вызов flock может блокировать выполнение на неопределённое время. Решение: использовать неблокирующий режим (LOCK_EX | LOCK_NB) и обрабатывать неудачу.
Как создать новый файл и записать в него данные, но не перезаписывать существующий?
Режим x (или x+) открывает файл только для записи, если файл не существует. Если файл существует, возвращается ошибка.
$fp = @fopen('newfile.txt', 'x'); // @ подавляет предупреждение
if (!$fp) {
echo 'Файл уже существует';
} else {
fwrite($fp, 'Первая запись');
fclose($fp);
}
Как записать бинарные данные (например, изображение) в файл?
Для бинарных данных используются те же функции, но режим b (binary) гарантирует корректную обработку на Windows.
$binaryData = pack('C*', 0x89, 0x50, 0x4E, 0x47); // заголовок PNG
$result = file_put_contents('image.png', $binaryData);
Как записать массив или объект в файл в виде JSON?
Преобразование данных в JSON с помощью json_encode и запись через file_put_contents.
$data = ['name' => 'John', 'age' => 30];
$json = json_encode($data, JSON_PRETTY_PRINT);
file_put_contents('data.json', $json);
Ошибки:
При кодировании могут возникать ошибки (рекурсия, неверная кодировка). Использовать JSON_THROW_ON_ERROR или проверять json_last_error().
Расширенные примеры записи в файл
1. Запись CSV с заголовками и разделителями
$fp = fopen('users.csv', 'w');
fputcsv($fp, ['ID', 'Имя', 'Email']);
fputcsv($fp, [1, 'Иван', 'ivan@example.com']);
fputcsv($fp, [2, 'Мария', 'maria@example.com']);
fclose($fp);
// Файл users.csv содержит:
// ID,Имя,Email
// 1,Иван,ivan@example.com
// 2,Мария,maria@example.com
Файл создан с правильным форматированием CSV.
2. Запись с проверкой прав доступа и созданием директории
$dir = 'logs';
$file = $dir . '/app.log';
if (!is_dir($dir)) {
mkdir($dir, 0755, true);
}
if (is_writable($dir)) {
file_put_contents($file, '[' . date('Y-m-d H:i:s') . '] Запись', FILE_APPEND | LOCK_EX);
} else {
error_log('Нет доступа к директории ' . $dir);
}
Директория создана, запись добавлена в конец файла с блокировкой.
3. Запись в несколько файлов из одного источника
$data = "Распределение данных\n";
$files = ['part1.txt', 'part2.txt', 'part3.txt'];
foreach ($files as $f) {
file_put_contents($f, $data, FILE_APPEND);
}
Каждый файл получил одинаковую строку в конец.
4. Использование потоков (stream) для записи больших объёмов
$src = fopen('large_source.txt', 'r');
$dst = fopen('large_dest.txt', 'w');
while (!feof($src)) {
$chunk = fread($src, 8192);
fwrite($dst, $chunk);
}
fclose($src);
fclose($dst);
Большой файл скопирован порциями, экономя память.
5. Запись в файл с указанием кодировки и обработкой UTF-8 BOM
// Записать UTF-8 текст с BOM для Excel
$content = pack('C*', 0xEF, 0xBB, 0xBF) . 'Привет, мир!';
file_put_contents('text_utf8.csv', $content);
Файл корректно открывается в Excel с русскими символами.
6. Запись с использованием временного файла и атомарной заменой
$tmp = tempnam(sys_get_temp_dir(), 'prefix');
file_put_contents($tmp, 'Новое содержимое');
rename($tmp, 'data.txt'); // атомарная замена
Файл data.txt обновлён без риска повреждения при сбое.
7. Запись данных из массива в файл построчно с форматированием
$lines = ['Строка 1', 'Строка 2', 'Строка 3'];
$content = implode(PHP_EOL, $lines) . PHP_EOL;
file_put_contents('lines.txt', $content);
Файл содержит три строки, каждая с переносом.