Чтение и запись сжатых файлов в PHP. Как использовать потоковые фильтры и обертки?

чтение и запись сжатых файлов в php. как использовать потоковые фильтры и обертки?

Потоковые обертки сжатых файлов

Для работы с содержимым сжатых файлов понадобятся специальные модули PHP-интерпретатора. Вы можете включить их поддержку при компиляции, указав флаги --with-zlib, --with-bz2 и --enable-zip. Также существует возможность установки модуля Zip через репозиторий PECL.

Каждое из этих расширений предоставляет ряд дополнительных функций или объектов для работы со сжатыми файлами. Вы можете ознакомиться с ними в официальной документации: Zlib, Bzip2 и Zip. В данном уроке будут рассмотрены более специфичные методы использования.

Файловые функции PHP поддерживают указание протоколов. Например, fopen() в первом параметре ожидает получить имя открываемого файла. Если в начало имени файла дописать протокол и домен «http://some-site.ru/some-file.txt», будет задействован специальный обработчик потока, который осуществит HTTP-запрос на указанный сервер для получения необходимого файла. Таким образом, вы выполните открытие файла с удаленного сервера.

Модули, работающие со сжатыми файлами в форматах gzip, zip и bz2, регистрируют собственные обработчики потоков, которые можно использовать аналогично приведенному выше примеру. Расширения Zlib, Bz2 и Zip предоставляют потоковые обработчики compress.zlib://, compress.bzip:// и zip:// соответственно.

Их использование предельно понятно. Применяя функции fopen(), file_get_contents(), file_put_contents(), fread() и т.д, вы дописываете перед именем файла соответствующие потоковые обертки. При этом после получения файлового дескриптора с помощью fopen() операции записи и чтения выполняются как с обычным несжатым файлом.

//Создаем файл в режиме записи c использованием обертки Zlib
$descriptor = fopen('compress.zlib://test-file.gz', 'w');
if ($descriptor !== null) {
    //Записываем короткий текст в файл
    fwrite($descriptor, 'Данный текст будет сжат в формате gzip');
    fclose($descriptor);

} else {
    echo 'Невозможно создать файл';
}

//Попробуем прочитать сжатый текст из созданного файла
echo file_get_contents('test-file.gz');
//результат: #�###ȱ � ##�U�vƎ�J���A��L4...

//Читаем из файла и распаковываем с помощью функции
echo zlib_decode(file_get_contents('test-file.gz'));
//результат: Данный текст будет сжат в формате gzip'

Заметка
Единственной особенностью потоковой обертки Zip является то, что этот формат осуществляет одновременное архивирование и сжатие. Таким образом, в одном файле с расширением .zip может храниться множество других сжатых файлов. Поэтому после указания потоковой обертки и имени архива нужно также дописать имя файла хранящегося внутри. Сделать это можно с помощью следующей конструкции «zip://имя_архивного_файла#имя_сжатого_файла».

Использование потоковых фильтров

Помимо оберток PHP реализует еще один вид взаимодействия с потоками. Их называют фильтрами. Основное отличие в том, что фильтры могут быть подключены к файловому дескриптору динамически в зависимости от каких-либо условий.

Модуль Zlib определяет фильтры zlib.deflate и zlib.inflate, отвечающие за распаковку и сжатие файла соответственно. Расширение Bz2 также имеет два фильтра bz2.compress и bz2.uncompress, выполняющие аналогичные операции.

Для применения фильтра к дескриптору уже открытого файла используется функция stream_filter_append(). Она принимает два основных параметра. В первом указывается дескриптор файла, который необходимо распаковать или сжать, а во втором имя фильтра. Функция вернет ресурс соответствующий установленному фильтру, либо false в случае ошибки. Данный ресурс можно использовать для открепления, ранее установленного потокового фильтра с помощью функции stream_filter_remove(), которая принимает всего один параметр — ресурс фильтра.

//Если файл не существует, записываем в него данные
if (!file_exists('test-file.gz')) {
    $descriptor = fopen('test-file.gz', 'w');
    stream_filter_append($descriptor, 'zlib.deflate');
    fwrite($descriptor, 'Прочитай меня если сможешь');
    fclose($descriptor);

    //пробуем прочитать строку из файла
    echo file_get_contents('test-file.gz');
    //результат: �0�bÅ}#�/��taÅ� #�\�za��~..

//иначе применяем фильтр распаковки и выводим текст
} else {
    $descriptor = fopen('test-file.gz', 'r');
    stream_filter_append($descriptor, 'zlib.inflate');
    echo fgets($descriptor);
    //результат: Прочитай меня если сможешь
}

Последние публикации