2016-07-12 9 views
0

私はzlibを経由compression filtersPHPの圧縮フィルタとgzcompress同じ結果を返さない

私のコードに私のコードを実行したときに、私は別の出力を得る:

<?php 
$data = 'zzzzzzzzzzzzzzzzzzzzzzzzzzz'; 

$params = array('level' => 6, 'window' => 15, 'memory' => 9); 
//$params = 6; 
$fp = fopen('php://memory', 'wb+'); 
stream_filter_append($fp, 'zlib.deflate', STREAM_FILTER_WRITE, $params); 
fputs($fp, $data); 
rewind($fp); 

echo bin2hex(stream_get_contents($fp)) . "\n"; 
echo bin2hex(gzcompress($data)) . "\n"; 

出力:

789c 
789cabaaa2260000bce3252d 

をそれはです789cはheader for normal compressionです。だから何が起きているのか分かりません。圧縮ストリームはPHPではうまくいきませんか?

感謝します。ありがとう!

答えて

1

問題は、文字列がDEFLATE作業バッファを埋めるのに非常に短すぎることです。また、ストリームが明示的に閉じられていないため、ストリームがまったく処理されず、フラッシュされません。 stream_get_contents()が呼び出されると、データはまだバッファに保留されています。

我々は、ランダムバイトの十分に大きなブロックを注入することによって、バッファフラッシュを強制する場合、いくつかのデータが実際にストリームに書き込まれます:

$data = openssl_random_pseudo_bytes(65536); 

$params = array('level' => 6, 'window' => 15, 'memory' => 9); 
$fp = fopen('php://memory', 'wb+'); 
stream_filter_append($fp, 'zlib.deflate', STREAM_FILTER_WRITE, $params); 
fputs($fp, $data); 
rewind($fp); 

echo substr(bin2hex(stream_get_contents($fp)), 0, 32) . "\n"; 
echo substr(bin2hex(gzcompress($data)), 0, 32) . "\n"; 

出力例(ちょうど16最初のバイトを表示):

789c000b80f47f453c070e41c557acdb 
789c000b80f47f453c070e41c557acdb 

一方、ZLIBヘッダー(78 9C =デフォルト圧縮)は、その内容が次のバイトに依存しないため、最初から安全に書き込むことができます。その場合、バッファは必要ありません。

+0

部分フラッシュを実行することはできません。 SSHで圧縮するには、必要があります。 quoting https://tools.ietf.org/html/rfc4253#section-6.2、 "*圧縮コンテキストは各キー交換の後に初期化され、あるパケットから次のパケットに渡されます。現在の圧縮ブロックが終了し、すべてのデータが出力されることを意味します。* " – neubert

+1

@neubertこれらの関数で部分的なフラッシュを完全に制御できるとは思いません。 '' memory '=> 1'を設定することでより頻繁なフラッシュが必要ですが、それが実行可能な解決策であるかどうかはわかりません。 – Arnauld

+0

この答えは正しいようですが、 'stream_get_contents()'の結果全体がまだ不完全であるためではありません。 'stream_filter_remove()'でフィルタを削除することで、強制的に圧縮を完了させることができます。少なくとも[this](https://3v4l.org/K1f3G)は動作します。それとも私は何かが恋しくなったのですか? –

関連する問題