Gzgets: примеры (PHP)

Функция gzgets для обработки сжатых данных в PHP
Раздел: Сжатие
gzgets(resource $stream, ?int $length = null): string|false

Функция gzgets в PHP

Основное назначение

gzgets — это встроенная PHP функция для построчного чтения данных из файла, сжатого с использованием алгоритма gzip. Она является частью модуля Zlib и применяется в ситуациях, когда необходимо обрабатывать большие сжатые файлы без полной распаковки в память. Функция полезна для лог-файлов, дампов баз данных или других текстовых ресурсов, хранящихся в сжатом виде.

Аргументы функции

Функция принимает до трёх параметров:

  1. $stream (обязательный) — ресурс, полученный после успешного открытия gzip-файла с помощью функции gzopen(). Указывает на сжатый поток для чтения.
  2. $length (необязательный) — максимальное количество байт для чтения. Если аргумент опущен или равен null, функция будет считывать данные до достижения конца строки или конца файла (EOF). Ограничение длины помогает управлять потреблением памяти.
  3. $mode (необязательный) — редко используемый параметр, который может влиять на обработку потока. Обычно не требуется для большинства задач.

Функция возвращает строку до $length - 1 байт, считанную из файла, или false в случае ошибки или достижения конца файла.

Примеры работы с gzgets

Базовое построчное чтение

Чтение всего файла строка за строкой без указания длины:

<?php
$handle = gzopen('example.txt.gz', 'r');
if ($handle) {
    while (($line = gzgets($handle)) !== false) {
        echo $line;
    }
    gzclose($handle);
}
?>
Первая строка файла.
Вторая строка текста.
...
Чтение с ограничением длины

Считывание строк с указанием максимального количества байт:

<?php
$handle = gzopen('example.txt.gz', 'r');
if ($handle) {
    echo gzgets($handle, 10); // Считает до 9 байт или до символа новой строки
    gzclose($handle);
}
?>
Первая ст

Альтернативы в PHP

gzfile и file_get_contents

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

$lines = gzfile('example.txt.gz'); // Массив строк

file_get_contents() в сочетании с потоковыми контекстами или обёрткой compress.zlib:// позволяет прочитать весь сжатый файл в одну строку.

$content = file_get_contents('compress.zlib://example.txt.gz');
Потоковые обёртки

Использование потоковых обёрток позволяет применять стандартные функции для работы с файлами, например fgets(), к сжатым данным без явного вызова функций модуля Zlib.

$handle = fopen('compress.zlib://example.txt.gz', 'r');
$line = fgets($handle); // Чтение строки
fclose($handle);

Аналоги в других языках

Python: модуль gzip

В Python для работы с gzip используется модуль gzip. Открытие файла аналогично работе с обычными файлами.

import gzip
with gzip.open('example.txt.gz', 'rt') as f:
    line = f.readline()  # Чтение одной строки
    # или построчное чтение всего файла
    for line in f:
        print(line)
JavaScript (Node.js): zlib модуль

В Node.js требуется сначала создать поток для чтения и распаковки, затем читать данные построчно с помощью модуля readline.

const zlib = require('zlib');
const fs = require('fs');
const readline = require('readline');

const fileStream = fs.createReadStream('example.txt.gz');
const gunzip = zlib.createGunzip();
const rl = readline.createInterface({
    input: gunzip
});

rl.on('line', (line) => {
    console.log(line);
});

fileStream.pipe(gunzip);
MySQL: компрессия при загрузке

MySQL не имеет прямой аналогии для построчного чтения сжатых файлов на стороне СУБД. Однако, можно загружать сжатые файлы с помощью команды LOAD DATA INFILE при условии, что клиентская сторона поддерживает распаковку.

Типичные ошибки

Игнорирование проверки ресурса

Попытка чтения из некорректного ресурса приводит к предупреждениям и false.

<?php
$line = gzgets(false); // Неверно
?>
Warning: gzgets() expects parameter 1 to be resource, bool given
Неправильная обработка конца файла

Использование простого сравнения с false без учёта возможности пустой строки.

<?php
while ($line = gzgets($handle)) { // Пустая строка тоже будет считана как false
    // ...
}
?>

Корректный способ — строгое сравнение:

while (($line = gzgets($handle)) !== false) { ... }
Забывание закрытия файла

Незакрытый ресурс может привести к утечке памяти.

Изменения в версиях PHP

В PHP 8.0.0 параметр $length стал опциональным (раньше требовалось указывать). Теперь можно передавать null для чтения всей строки без ограничений по длине.

// До PHP 8.0
$line = gzgets($handle, 1024); // Длина обязательна
// Начиная с PHP 8.0
$line = gzgets($handle); // Корректно, читает до конца строки

Расширенные примеры

Обработка CSV из gzip-файла

Чтение и парсинг сжатого CSV файла построчно.

Пример php
<?php
$handle = gzopen('data.csv.gz', 'r');
if ($handle) {
    while (($line = gzgets($handle)) !== false) {
        $fields = str_getcsv($line);
        // Обработка массива $fields
        print_r($fields);
    }
    gzclose($handle);
}
?>
Чтение с использованием генератора

Создание генератора для эффективного чтения больших файлов.

Пример php
<?php
function readGzLines(string $filename): Generator {
    $handle = gzopen($filename, 'r');
    if (!$handle) return;
    try {
        while (($line = gzgets($handle)) !== false) {
            yield $line;
        }
    } finally {
        gzclose($handle);
    }
}

foreach (readGzLines('huge.log.gz') as $line) {
    // Обработка каждой строки
}
?>
Чтение бинарных данных с известной структурой

Использование gzgets для чтения строк из сжатого бинарного файла с фиксированными заголовками.

Пример php
<?php
$handle = gzopen('packed.bin.gz', 'rb'); // Бинарный режим
$header = gzgets($handle, 100); // Чтение заголовка длиной 100 байт
// Дальнейшая обработка
?>

PHP gzgets function comments

En
Gzgets Get line from file pointer