Gzseek: примеры (PHP)
gzseek(resource $stream, int $offset, int $whence = SEEK_SET): intФункция gzseek устанавливает указатель позиции файла для gzip-ресурса. Она применяется для произвольного доступа к данным внутри сжатого файла, открытого с помощью gzopen(), что позволяет читать содержимое не с начала, а с определенного места.
- stream (resource) - Указатель на gz-файл, который должен быть действительным и успешно открытым с помощью
gzopen(). - offset (int) - Смещение в байтах. В отличие от обычных файлов, смещение указывается в распакованных данных.
- whence (int - необязательный) - Определяет точку отсчета для смещения. Принимает значения:
SEEK_SET(по умолчанию - отсчет от начала файла),SEEK_CUR(от текущей позиции),SEEK_END(от конца файла). Добавлен в PHP 7.3.0.
Функция возвращает 0 в случае успеха, и -1 в случае неудачи. Для gzip-файлов, которые не поддерживают произвольный доступ (например, при чтении из стандартного ввода), функция всегда возвращает -1.
<?php
$fp = gzopen('data.gz', 'r');
// Перемещаемся на 100-й байт распакованных данных от начала файла
$result = gzseek($fp, 100);
echo "Результат gzseek: $result\n"; // 0 - успех
// Читаем данные с новой позиции
echo gzread($fp, 20);
gzclose($fp);
?>Результат gzseek: 0 [следующие 20 байт содержимого файла, начиная со 100-го]
<?php
$fp = gzopen('data.gz', 'r');
gzread($fp, 50); // Читаем 50 байт, позиция сдвигается
// Перемещаемся на 30 байт вперед от текущей позиции
$result = gzseek($fp, 30, SEEK_CUR);
echo "Результат: $result\n";
gzclose($fp);
?>Результат: 0
<?php
$fp = gzopen('data.gz', 'r');
// Попытка перейти за пределы небольшого файла
$result = gzseek($fp, 1000000);
echo "Результат: $result\n"; // -1
// Указатель остается на прежней позиции (начало файла)
echo "Текущая позиция: " . gztell($fp) . "\n";
gzclose($fp);
?>Результат: -1 Текущая позиция: 0
- gzrewind() - Сбрасывает указатель позиции в начало gz-файла. Удобна для повторного чтения файла с начала.
- gztell() - Возвращает текущую позицию указателя чтения/записи в распакованных данных. Часто используется вместе с
gzseek()для определения позиции. - fseek() - Аналогичная функция для работы с несжатыми файлами. Работает с обычными файловыми указателями, но не поддерживает gz-ресурсы.
Выбор функции зависит от задачи: gzseek() нужна для произвольного доступа внутри сжатого файла, gzrewind() - для быстрого возврата в начало, а gztell() - для диагностики текущего положения.
import gzip
with gzip.open('data.gz', 'rb') as f:
f.seek(100) # Перемещение на 100-й байт распакованных данных
data = f.read(20)
print(data)[байты со 100-го по 119-й]
Прямого аналога в чистом виде нет. Обычно требуется распаковать весь файл в память или буфер, затем использовать Buffer.slice() или позиционирование в потоке.
MySQL использует сжатие для передачи данных, но не предоставляет функций для позиционирования внутри сжатого потока на уровне запросов. Работа с архивами обычно происходит вне СУБД.
<?php
$result = gzseek('not_a_resource', 10);
echo "Результат: $result\n";
?>Warning: gzseek() expects parameter 1 to be resource, string given Результат: (пусто или false в зависимости от конфигурации)
<?php
$fp = gzopen('output.gz', 'w');
$result = gzseek($fp, 10);
echo "Результат: $result\n"; // -1
gzclose($fp);
?>Результат: -1
<?php
// В PHP 7.2 и ниже
$fp = gzopen('data.gz', 'r');
$result = gzseek($fp, 10, SEEK_CUR); // Третий аргумент игнорируется
echo "Результат: $result\n";
gzclose($fp);
?>Результат: 0 (смещение считается от начала файла, а не от текущей позиции)
- PHP 7.3.0 - Добавлен необязательный третий аргумент
whence. Это позволило использовать значенияSEEK_SET,SEEK_CURиSEEK_ENDдля гибкого позиционирования, аналогично функцииfseek(). - До PHP 7.3 - Функция поддерживала только позиционирование от начала файла (
SEEK_SET), а третий аргумент, если он передавался, игнорировался.
<?php
$fp = gzopen('log.gz', 'r');
// Переход на 50 байт от конца распакованного файла
if (gzseek($fp, -50, SEEK_END) === 0) {
echo "Последние 50 байт файла:\n";
echo gzread($fp, 50);
} else {
echo "Файл слишком мал для такого смещения.\n";
}
gzclose($fp);
?>Последние 50 байт файла: [содержимое последних 50 байт]
<?php
// Ищем позицию, примерно соответствующую 75% файла
$fp = gzopen('huge_log.gz', 'r');
gzseek($fp, 0, SEEK_END);
$file_size = gztell($fp); // Узнаем размер распакованного файла
$target_pos = (int)($file_size * 0.75);
gzseek($fp, $target_pos);
// Пропускаем возможную "середину" строки
fgets($fp); // Читаем остаток строки, чтобы выровнять позицию на начало следующей строки
// Читаем следующие 10 строк
for ($i = 0; $i < 10; $i++) {
$line = fgets($fp);
if ($line === false) break;
echo "Строка " . ($i+1) . ": $line";
}
gzclose($fp);
?>Строка 1: [строка лога] Строка 2: [строка лога] ... Строка 10: [строка лога]
<?php
// Предположим, что в файле хранятся блоки фиксированного размера (1000 байт)
// Создаем индекс: [номер_блока => позиция_в_файле]
$index = [];
$fp = gzopen('archive.gz', 'r');
$block_num = 0;
while (!gzeof($fp)) {
$index[$block_num] = gztell($fp); // Запоминаем позицию начала блока
// Пропускаем блок данных (читаем и игнорируем)
gzread($fp, 1000);
$block_num++;
}
// Теперь можно быстро прочитать любой блок по его номеру
$block_to_read = 42;
if (isset($index[$block_to_read])) {
gzseek($fp, $index[$block_to_read]);
$block_data = gzread($fp, 1000);
echo "Содержимое блока $block_to_read: $block_data\n";
}
gzclose($fp);
?>Содержимое блока 42: [данные блока]