Методы работы с текстовыми строками в файлах через PHP
Основные способы работы со строками в файлах PHP
Базовый метод: file_put_contents и file_get_contents
Как быстро записать строку в файл и прочитать её целиком?
Для задач, где файл не превышает десятков мегабайт, рекомендуется использовать компактные функции file_put_contents и file_get_contents. Они избавляют от необходимости открывать и закрывать файл вручную.
<?php
$filename = 'message.txt';
$data = "Привет, мир!\nВторая строка.";
file_put_contents($filename, $data);
$result = file_get_contents($filename);
echo $result;
?>
Результат выполнения: на экран будет выведена строка "Привет, мир!" и "Вторая строка." каждая с новой строки.
Пояснения:
1. file_put_contents автоматически открывает файл на запись, записывает строку и закрывает. Если файла нет, он создается. Если файл существует, по умолчанию перезаписывается. Для добавления данных используется флаг FILE_APPEND.
2. file_get_contents читает все содержимое файла в виде строки. Удобно для конфигурационных файлов, шаблонов и т.п.
Возможные проблемы:
Недостаток памяти при очень больших файлах (сотни мегабайт). Решение: использовать построчное чтение fgets.
Ошибка доступа (Permission denied). Решение: проверить права на директорию, выставить chmod 755 или 644.
Нельзя работать с бинарными данными (например, изображениями) без дополнительной настройки, но file_get_contents поддерживает бинарный режим.
Когда применять:
Сохранение коротких текстов, настроек, результатов работы скрипта в виде строки. Быстрое копирование содержимого файла.
Вариант 1: Построчная обработка через fopen, fgets, fwrite
Как обработать большой файл, не загружая его целиком в память?
Для файлов размером более 10-20 МБ лучше использовать построчное чтение. Функция fopen открывает файл и возвращает указатель. fgets читает одну строку (до символа новой строки или указанной длины).
<?php
$handle = fopen('bigfile.log', 'r');
if ($handle) {
$output = fopen('filtered.log', 'w');
while (($buffer = fgets($handle, 4096)) !== false) {
// фильтрация: сохраняем только строки, содержащие слово "ERROR"
if (strpos($buffer, 'ERROR') !== false) {
fwrite($output, $buffer);
}
}
fclose($handle);
fclose($output);
}
?>
Пояснения:
fopen('bigfile.log', 'r') открывает файл только для чтения. Второй аргумент 'r' означает чтение с начала файла.
Цикл while читает строки по очереди. Как только fgets возвращает false, файл заканчивается. Важно использовать !== false, так как пустая строка (например, конец файла) может быть false при ошибках.
fwrite записывает строку в выходной файл. Каждый вызов fgets читает следующую строку.
Типичные ошибки:
Забыть закрыть файл через fclose - утечка ресурсов.
Неправильный режим открытия: 'w' удалит существующее содержимое. Для добавления используйте 'a'.
Если файл очень большой, fgets может вернуть false не только при конце файла, но и при ошибке. Лучше проверять feof.
Когда применять:
Обработка лог-файлов, файлов с большим количеством строк (миллионы), где необходимо фильтровать или преобразовывать каждую строку.
Вариант 2: Чтение фиксированного количества байт через fread
Как прочитать из файла ровно N байт или заданный фрагмент?
Функция fread($handle, $length) читает $length байт из файла. Полезна для бинарных файлов (изображения, архивы) или когда нужно прочитать фиксированный заголовок.
<?php
$file = fopen('image.jpg', 'rb'); // двоичный режим
$header = fread($file, 4); // читаем первые 4 байта (сигнатура JPEG: 0xFF 0xD8 0xFF 0xE0)
echo bin2hex($header); // выводим в шестнадцатеричном виде
fclose($file);
?>
Результат: например, ffd8ffe0 - начало JPEG.
Пояснения:
Режим 'rb' указывает на чтение в двоичном режиме (для Windows актуально, чтобы не преобразовывать переводы строк).
fread может прочитать меньше байт, чем запрошено, если достигнут конец файла. Необходимо проверять длину прочитанного через strlen($header).
Проблемы:
При использовании fread для текстового файла (без 'b') на Windows символы \r\n могут быть преобразованы, что исказит длину. Решение: всегда указывать 'b' для бинарных файлов.
Неверный указатель при открытии файла - проверить на false.
Когда применять:
Чтение заголовков файлов, работа с бинарными протоколами, разбор структурированных данных фиксированной длины.
Вариант 3: Преобразование файла в массив строк через file()
Как получить массив строк файла для последующей обработки?
Функция file($filename) считывает все строки файла в массив. Может быть полезна для небольших конфигурационных или текстовых файлов, когда нужен произвольный доступ по номеру строки.
<?php
$lines = file('config.ini', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
foreach ($lines as $num => $line) {
echo "Строка " . ($num+1) . ": " . htmlspecialchars($line) . "<br>\n";
}
?>
Результат: вывод каждой строки с номером, пустые строки пропущены.
Пояснения:
Флаг FILE_IGNORE_NEW_LINES удаляет символы новой строки из каждого элемента массива.
FILE_SKIP_EMPTY_LINES пропускает пустые строки (строки, состоящие только из символов перевода).
Проблемы:
При больших файлах массив может занять много памяти. Решение: использовать построчное чтение.
Строки могут содержать бинарные символы, которые испортят вывод. Рекомендуется использовать htmlspecialchars при выводе.
Когда применять:
Парсинг простых текстовых файлов, чтение файлов с перечислением (списки, словари), загрузка небольшого файла в память для многократного обращения.
Расширенные примеры работы со строками в файлах PHP
Пример 1: Запись и чтение CSV с помощью fputcsv и fgetcsv
<?php
$data = [
['Имя', 'Возраст', 'Город'],
['Иван', 25, 'Москва'],
['Мария', 30, 'Санкт-Петербург']
];
$file = fopen('users.csv', 'w');
foreach ($data as $row) {
fputcsv($file, $row);
}
fclose($file);
// чтение
$file = fopen('users.csv', 'r');
while (($row = fgetcsv($file)) !== false) {
print_r($row);
}
fclose($file);
?>
Array ( [0] => Имя [1] => Возраст [2] => Город ) Array ( [0] => Иван [1] => 25 [2] => Москва ) Array ( [0] => Мария [1] => 30 [2] => Санкт-Петербург )
Данный пример показывает, как записать двумерный массив в CSV-файл и затем прочитать его обратно. fputcsv автоматически экранирует поля и разделяет их запятой. fgetcsv разбирает строку на массив. Важно: при чтении рекомендуется проверять, что строка не пустая.
Пример 2: Поиск и замена с регулярными выражениями в файле
<?php
$source = fopen('source.txt', 'r');
$target = fopen('target.txt', 'w');
while (($line = fgets($source)) !== false) {
// Замена всех дат формата 2023-01-01 на 01.01.2023
$line = preg_replace('/(\d{4})-(\d{2})-(\d{2})/', '$3.$2.$1', $line);
fwrite($target, $line);
}
fclose($source);
fclose($target);
echo "Готово";
?>
Предположим, файл source.txt содержит строку "Файл создан 2023-01-01.". После выполнения в target.txt будет "Файл создан 01.01.2023.". Регулярное выражение захватывает год, месяц и день, а замена переставляет их. Построчная обработка позволяет работать с файлами любого размера.
Пример 3: Использование fscanf для разбора структурированных строк
<?php
$file = fopen('data.txt', 'r');
while ($fields = fscanf($file, "ID: %d, Name: %s")) {
list($id, $name) = $fields;
echo "ID=$id, Name=$name\n";
}
fclose($file);
?>
ID=1, Name=Alice ID=2, Name=Bob
Функция fscanf считывает строку и разбирает её по заданному формату. В примере файл data.txt содержит строки "ID: 1, Name: Alice" и т.д. Формат задаёт, что ожидается целое число (%d) после "ID: " и строка (%s) после "Name: ". Такой подход удобен для log-файлов с фиксированной структурой.
Пример 4: Разбиение большого файла на части по N строк
<?php
$source = fopen('big.txt', 'r');
$part = 1;
$maxLines = 100;
$lineCount = 0;
$handle = null;
while (($line = fgets($source)) !== false) {
if ($lineCount % $maxLines == 0) {
if ($handle) fclose($handle);
$handle = fopen("part_$part.txt", 'w');
$part++;
}
fwrite($handle, $line);
$lineCount++;
}
fclose($handle);
fclose($source);
?>
Результат: файлы part_1.txt, part_2.txt и т.д., каждый содержит не более 100 строк. Алгоритм: отслеживается количество прочитанных строк; когда остаток от деления на 100 равен нулю, открывается новый выходной файл. Такой метод позволяет обрабатывать файл без загрузки в память целиком.