ちょうど昨日、
LZWアルゴリズムで文字列を圧縮/解凍するための作業クラス/モジュールが見つからないという状況に遭遇しました。 より正確には:jsCompress-jsDecompress-動作します。 PhpCompress-PhpDecompress-動作します。 ただし、jsCompress-PhpDecompressは、まったく未知のものを返すか、空の文字列を返します。 正直なところ、ANSIにそのような問題はないかもしれませんが、utf-8では非常に明確に表示されます。 問題を解決するのに数時間費やしたので、Habrで作業する準備ができた関数を公開することにしました。
LZWアルゴリズムでの圧縮の仕組みについては説明しません。 これは
wikiで美しく説明されてい
ます 。
PHPの
code.google.com/p/php-lzw/とJS
gist.github.com/843889の既製の関数とクラスが基礎として採用されました。
JS関数は変更されずに「そのまま」残されます
function lzw_encode(s) { var dict = {}; var data = (s + "").split(""); var out = []; var currChar; var phrase = data[0]; var code = 256; for (var i=1; i<data.length; i++) { currChar=data[i]; if (dict[phrase + currChar] != null) { phrase += currChar; } else { out.push(phrase.length > 1 ? dict[phrase] : phrase.charCodeAt(0)); dict[phrase + currChar] = code; code++; phrase=currChar; } } out.push(phrase.length > 1 ? dict[phrase] : phrase.charCodeAt(0)); for (var i=0; i<out.length; i++) { out[i] = String.fromCharCode(out[i]); } return out.join(""); }
ただし、PHP関数は少し修正する必要がありました。 LZWアルゴリズムによって圧縮された行には、255(ala unicode)よりも大きい文字コードを含めることができます。また、この非常にマルチバイト文字のコードを返す1つの関数mb_ordを
コピーして貼り付けます。
function mb_ord($string) { if (extension_loaded('mbstring') === true) { mb_language('Neutral'); mb_internal_encoding('UTF-8'); mb_detect_order(array('UTF-8', 'ISO-8859-15', 'ISO-8859-1', 'ASCII')); $result = unpack('N', mb_convert_encoding($string, 'UCS-4BE', 'UTF-8')); if (is_array($result) === true) return $result[1]; } return ord($string); } function lzw_decompress($binary) { $dictionary_count = 256; $bits = 8; $codes = array(); $rest = 0; $rest_length = 0; mb_internal_encoding("UTF-8"); for ($i = 0; $i < mb_strlen($binary); $i++ ) {$codes[] = mb_ord(mb_substr($binary, $i, 1)); }
もちろん、LZWで圧縮された文字列を正しく送信するには、送信前にbase64でエンコードし、解凍する前にデコードする必要があります。 これで問題はないはずです。 PHP側では、すべてがスムーズですが、JS
では、同じアルゴリズムがインターネットのどこにでもあります
これらの関数には特に新しいものはありませんが、おそらくこの記事は他の人の時間を大幅に節約するでしょう。 クライアント側でデータを圧縮する必要があるかもしれないものについては、コメントに書きました。