Как прочитать файл в PHP: основные и продвинутые методы

Раздел: Разработка на PHP -> Работа с файлами

Основные способы чтения файлов в PHP

Как прочитать весь файл в одну строку без лишних операций?

Наиболее эффективный и простой способ - функция file_get_contents. Она считывает весь файл в строку и автоматически закрывает файловый дескриптор. Подходит для небольших файлов (до нескольких мегабайт).


$content = file_get_contents('/path/to/file.txt');
echo $content;
  

Если файл не найден, функция вернёт false. Рекомендуется проверять результат:


$content = file_get_contents('missing.txt');
if ($content === false) {
    die('Ошибка чтения файла');
}
  

Проблемы: при чтении очень больших файлов (например, >100MB) может не хватить памяти. Также функция не подходит для потоковой обработки. Возможна ошибка включения удалённых файлов (allow_url_fopen = Off). Решение - использовать fopen с fread или включить allow_url_fopen в php.ini.

Как читать файл порциями, не загружая его целиком в память?

Для этого используется пара fopen + fread + fclose. Открываем файловый указатель, читаем нужное количество байт и закрываем. Это позволяет обрабатывать файлы любого размера.


$handle = fopen('large_file.log', 'rb');
if ($handle) {
    while (!feof($handle)) {
        $chunk = fread($handle, 8192); // 8KB
        // обрабатываем $chunk
        echo $chunk;
    }
    fclose($handle);
}
  

Цель: обработка больших логов, видеофайлов или архивов.

Ошибки: если файл не существует или нет прав на чтение, fopen вернёт false. Нужно всегда явно закрывать файл через fclose. При использовании бинарного режима ('rb' вместо 'r') на Windows корректно читаются бинарные данные.

Как обрабатывать файл построчно?

Функция fgets читает одну строку (до символа новой строки). Удобно для текстовых файлов (логи, конфиги, CSV).


$handle = fopen('text.txt', 'r');
if ($handle) {
    while (($line = fgets($handle)) !== false) {
        echo "Строка: " . $line;
    }
    fclose($handle);
}
  

Длина строки по умолчанию не ограничена, но можно указать второй параметр (максимум байт).

Проблема: если строки очень длинные (>8KB по умолчанию), fgets может прочитать только часть строки. Рекомендуется указывать размер буфера или использовать stream_get_line.

Как получить содержимое файла в виде массива строк?

Функция file считывает весь файл и возвращает массив, где каждый элемент - строка. Удобно для простого построчного доступа.


$lines = file('data.txt');
foreach ($lines as $lineNum => $line) {
    echo "Строка $lineNum: $line";
}
  

Также можно пропустить пустые строки (флаг FILE_SKIP_EMPTY_LINES) или не обрабатывать символы новой строки (FILE_IGNORE_NEW_LINES).

Проблемы: как и file_get_contents, требует много памяти для больших файлов. Флаг FILE_IGNORE_NEW_LINES удобен при дальнейшей обработке.

Как вывести содержимое файла непосредственно в браузер без сохранения в переменную?

Функция readfile считывает файл и записывает его в буфер вывода. Полезна для отдачи статических файлов (изображений, PDF).


$filename = 'image.jpg';
if (file_exists($filename)) {
    header('Content-Type: image/jpeg');
    readfile($filename);
}
  

Возвращает количество прочитанных байт. Можно использовать для подсчёта размера.

Проблемы: не подходит для дальнейшей обработки содержимого, только для вывода. Нужно правильно установить заголовки.

Как читать файл с помощью объектно-ориентированного подхода?

Класс SplFileObject предоставляет удобный интерфейс для работы с файлами. Поддерживает итерацию по строкам, управление курсором.


$file = new SplFileObject('data.txt');
$file->setFlags(SplFileObject::DROP_NEW_LINE); // убираем 

foreach ($file as $lineNum => $line) {
    echo "Строка $lineNum: $line\n";
}
  

Можно получить количество строк, перемещаться по файлу, работать с CSV (fgetcsv).

Ошибки: конструктор выбрасывает RuntimeException если файл не найден. Нужно обрабатывать исключения.

Как читать удалённый файл по HTTP с дополнительными опциями?

Для чтения URL используется file_get_contents с контекстом потока (stream_context_create). Это позволяет задать таймаут, заголовки, метод запроса.


$options = [
    'http' => [
        'method' => 'GET',
        'header' => "User-Agent: MyApp/1.0\r\n",
        'timeout' => 10
    ]
];
$context = stream_context_create($options);
$result = file_get_contents('https://api.example.com/data.json', false, $context);
if ($result !== false) {
    echo $result;
}
  

Цель: получение данных с внешних API, парсинг RSS.

Частая ошибка: allow_url_fopen выключен. Альтернатива - curl. Также нужно обрабатывать ошибки HTTP (404, 500) - проверять переменную $http_response_header.

Выбор метода зависит от размера файла, требуемого способа обработки и объёма памяти. Для простых небольших файлов - file_get_contents. Для построчной обработки - fgets или SplFileObject. Для больших объёмов - fopen+fread.

Расширенные примеры чтения файлов

В этом разделе приведены сложные случаи использования функций чтения файлов в PHP.

1. Чтение CSV файла с преобразованием

Пример

$file = new SplFileObject('data.csv');
$file->setFlags(SplFileObject::READ_CSV | SplFileObject::SKIP_EMPTY);
foreach ($file as $row) {
    if ($row !== false) {
        // $row - массив полей
        echo implode(' | ', $row) . "\n";
    }
}
Иван | ivan@example.com
Мария | maria@example.net

Пояснение: флаг READ_CSV автоматически парсит каждую строку как CSV. SKIP_EMPTY пропускает пустые строки.

2. Генератор для построчного чтения больших файлов

Пример

function readFileLines($filename) {
    $handle = fopen($filename, 'r');
    while (!feof($handle)) {
        yield fgets($handle);
    }
    fclose($handle);
}

foreach (readFileLines('huge.log') as $line) {
    // обработка строки без загрузки всего файла
    if (strpos($line, 'ERROR') !== false) {
        echo $line;
    }
}

Результат: только строки с 'ERROR' выводятся. Память почти не расходуется.

3. Потоковая фильтрация (распаковка gzip)

Пример

$handle = fopen('compressed.log.gz', 'rb');
stream_filter_append($handle, 'zlib.inflate', STREAM_FILTER_READ);
while (!feof($handle)) {
    $chunk = fread($handle, 4096);
    echo $chunk;
}
fclose($handle);

Пояснение: фильтр zlib.inflate распаковывает данные на лету. Аналогично можно применить фильтры для convert.cyr, string.toupper и др.

4. Чтение бинарного файла (например, заголовок PNG)

Пример

$handle = fopen('image.png', 'rb');
$header = fread($handle, 8); // первые 8 байт сигнатуры PNG
$signature = unpack('H*', $header); // hex
echo "Сигнатура: " . $signature[1] . "\n"; // 89504e470d0a1a0a
fclose($handle);
Сигнатура: 89504e470d0a1a0a

5. Параллельное чтение с помощью нескольких дескрипторов

Пример

$files = ['a.txt', 'b.txt', 'c.txt'];
$handles = [];
foreach ($files as $f) {
    $handles[$f] = fopen($f, 'r');
}
// Чтение поочередно по одной строке
while (count($handles) > 0) {
    foreach ($handles as $name => $handle) {
        if (feof($handle)) {
            fclose($handle);
            unset($handles[$name]);
            continue;
        }
        $line = fgets($handle);
        echo "$name: $line";
    }
}

Результат: строки из трёх файлов чередуются.

6. Использование readfile с подсчётом размера

Пример

$bytes = readfile('large.bin');
echo "Sent $bytes bytes";
Sent 1048576 bytes

readfile возвращает количество байт, что удобно для мониторинга.

Чтение содержимого файла в PHP - comments

En
Php file content (php)