PHP Conference Nagoya 2025

inflate_add

(PHP 7, PHP 8)

inflate_addインクリメンタルにエンコードされたデータを解凍する

説明

inflate_add(InflateContext $context, string $data, int $flush_mode = ZLIB_SYNC_FLUSH): string|false

指定された context でエンコードされたデータをインクリメンタルに解凍します。

制限: GZIP 圧縮されたデータからは、ヘッダ情報は利用できません。

パラメータ

context

inflate_init() で作られたコンテクスト

data

圧縮されたデータのチャンク

flush_mode

ZLIB_BLOCK, ZLIB_NO_FLUSH, ZLIB_PARTIAL_FLUSH, ZLIB_SYNC_FLUSH (デフォルト), ZLIB_FULL_FLUSH, ZLIB_FINISH のいずれか。 通常は、圧縮率を最大にするために、 ZLIB_NO_FLUSH を指定するでしょうし、 データの最後のチャンクで終了させるために ZLIB_FINISH を指定するでしょう。 これらの定数の詳細な説明は » zlib manual を参照ください。

戻り値

解凍されたデータのチャンクを返します。 失敗した場合に false を返します

エラー / 例外

不正な引数が与えられた場合、データの解凍にはあらかじめ設定された辞書が必要なのに 何も指定されなかった場合、圧縮データが壊れていたり、不正なチェックサムだった場合、 エラーレベル E_WARNING が生成されます。

変更履歴

バージョン 説明
8.0.0 context は、 InflateContext クラスのインスタンスを期待するようになりました。 これより前のバージョンでは、resource を期待していました。

参考

  • inflate_init() - インクリメンタルな解凍コンテキストを初期化する
add a note

User Contributed Notes 1 note

up
0
burp at -only-in-German-fuerspam dot de
1 year ago
It's not obvious how to use this for _incremental_ decompression:
You feed _the compressed data_ into inflate_add() _in pieces_.
The internal state of the zlib context will make sure than you can split at any point and still get the correct total data out, as long as you keep reading until the end.

In this way, you don't have to hold the complete uncompressed data in memory at any one time (and don't have to materialize it either as a file for gzopen() etc.), allowing you to parse files much bigger than the available php memory limit.

<?php
/* a good step size depends on the input's level of compression,
unfortunately there's no obvious way to know that beforehand;
in doubt instead choose a rather small value and glue the pieces together,
until there's enough data for processing */
$step = 500000;

$dataGz = load_gzip_compressed_data_to_string();

$start = 0;
$outLen = 0;
$ctxt = inflate_init(ZLIB_ENCODING_GZIP);
$status = inflate_get_status($inflCtxt);

while(
$status == ZLIB_OK) {
$split = substr($dataGz, $start, $step);
$dataFragment = inflate_add($inflCtxt, $split);
/* process fragment, potentially keep parts across iterations */
$outLen += strlen($dataFragment);
$status = inflate_get_status($inflCtxt);
$start += $step;
}
echo
'Input: ' . strlen($dataGz) . ' Bytes / Output: ' . $outLen . ' Bytes.';
?>

N.B.: Archives of extremely high compression will still bomb out with a stupid and unnecessary memory exhaustion, as it's not possible to define a limit in inflate_init() similar to gzuncompress().
To Top