2016-06-30 13 views
18

私は最近、いくつかのファイルを圧縮していましたが、私はbase64でエンコードされたデータが圧縮されているように見えました。それは
13,2 MiB/429,7 MiB = 0,0314,9 MiB/s1:28 なぜbase64でエンコードされたデータが圧縮されるのですか?

  • base64xz -9を経由して圧縮:

    • オリジナルファイル:xz -9経由429,7のMIB
    • 湿布ここでは一例である
      26,7 MiB/580,4 MiB = 0,0462,6 MiB/s3:47
    • base64元の圧縮されたxzファイル:
      17,8 MiBほとんど時間がない=

    サイズが予想1.33x増加は、だから何観察できることということです。

    • XZは
    • base64でエンコードされたデータは圧縮されません。本当に良い☺を圧縮よく、それはunencoded圧縮ファイルの2倍です
    • base64-then-compressは大幅に悪化し、compよりも遅くなりますress-then-base64

    これはどのようにすることができますか? Base64はロスレス、リバーシブルなアルゴリズムですが、なぜ圧縮にそれほど影響しますか? (gzipで同様の結果を出してみました)。

    base64-then-compressファイルがありますが、ほとんどの場合、入力ファイルを制御できません。実際の情報密度base64でエンコードされたファイルの名前(またはそれが何であれ)は、エンコードされていないバージョンとほぼ同じで、同様に圧縮可能です。

  • +0

    "_base64-then-compress_は_compress-then-base64_よりも大幅に悪く、遅くなります。"という2つの意味は無関係です。 – MSalters

    答えて

    4

    圧縮は必然的に複数のビットに作用する操作です。個々の "0"と "1"を圧縮しようとすると、何の利益も得られません。それでも、圧縮は通常、一度に限られたビットのセットで動作します。 xzのLZMAアルゴリズムは、一度に36億ビットすべてを考慮しません。はるかに小さい文字列(< 273バイト)を調べます。

    ここでbase-64エンコーディングの動作を確認します。3バイト(24ビット)のワードを4バイトワードに置き換え、256個の可能な値のうち64個だけを使用します。これはあなたにx1.33の成長を与えます。

    このような成長によって、一部の部分文字列がエンコーダの最大部分文字列サイズを超えて大きくなる必要があることは明らかです。これにより、それらはもはや単一の部分文字列として圧縮されるのではなく、実際には2つの別々の部分文字列として圧縮されます。

    圧縮(97%)のがあるので、非常に長い入力部分文字列全体が圧縮されているように見えます。これは、エンコーダーが処理できる最大長を超えてベース64が拡張された多くの部分文字列も持つことを意味します。

    38

    ほとんどの一般的な圧縮アルゴリズムは、ので動作します。

    のは、次の文字列を考えてみましょう:

    "XXXXYYYYXXXXYYYY" 
    
    • Aランレングス符号化アルゴリズムは言うだろう:を「それは4だ 'X'、4 'Y' に続いて、4 'のX' が続きます"0XXXYYY"という文字列が続き、同じ文字列が続きます.2番目の文字列を1番目の文字列への参照に置き換えましょう。 "
    • ハフマンコーディングアルゴリズムは次のようになります。"その文字列には2つのシンボルしかないので、シンボルあたり1ビットしか使用できません。"

    ここで、私たちの文字列をBase64でエンコードしましょう。ここでは、何を得るのです。

    "WFhYWFlZWVlYWFhYWVlZWQ==" 
    

    すべてのアルゴリズムが今言っている:「つまり混乱のどのような?」。そして、彼らはその弦を非常にうまく圧縮しないでしょう。各出力

    Input bytes : aaaaaaaa bbbbbbbb cccccccc 
    6-bit repacking: 00aaaaaa 00aabbbb 00bbbbcc 00cccccc 
    

    :リマインダーとして

    、Base64では、基本的に(0 ... 63)の4バイトのグループに(0 ... 255)で3バイトの再エンコード基により動作しますバイトは印刷可能なASCII文字に変換されます。慣例により、これらの文字は(ここではマークの付いたすべての10文字)です。

    0   1   2   3   4   5   6 
    ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/ 
    

    たとえば、上の例の文字列が16進数で0x58に等しい3バイトのグループ(文字「X」のASCIIコード)で始まります。またはバイナリに:01011000.のは、Base64エンコードを適用してみましょう:私たちがきたので

    Input bytes  : 0x58  0x58  0x58 
    As binary  : 01011000 01011000 01011000 
    6-bit repacking : 00010110 00000101 00100001 00011000 
    As decimal  : 22  5  33  24 
    Base64 characters: 'W'  'F'  'h'  'Y' 
    Output bytes  : 0x57  0x46  0x68  0x59 
    

    は基本的には、元のデータストリームには明らかだったパターン「3回のバイト0x58は」符号化されたデータストリームにはもはや明白ではありませんバイトを6ビットのパケットに分割し、それらを現在ランダムであるように見える新しいバイトにマッピングしました。

    つまり、ほとんどの圧縮アルゴリズムが依存する元のバイト配列が壊れています。

    どのような圧縮方法を使用しても、通常はアルゴリズムのパフォーマンスに重大な影響を与えます。そのため、常に最初に圧縮し、2番目にエンコードする必要があります。

    これは、さらに暗号化に当てはまります。まず圧縮し、2番目を暗号化します。

    EDIT - XZが使用している - - ビットストリームではなく、バイトストリームに取り組んでいるMSaltersは、LZMAは気づいたようLZMA

    に関する注意。

    それでも、このアルゴリズムはまた、私の以前の説明と基本的に一致しているように、Base64エンコーディングに苦しむだろう。

    Input bytes  : 0x58  0x58  0x58 
    As binary  : 01011000 01011000 01011000 
    (see above for the details of Base64 encoding) 
    Output bytes  : 0x57  0x46  0x68  0x59 
    As binary  : 01010111 01000110 01101000 01011001 
    

    でもビットレベルで働くことによって、それは内のパターンを認識する方がはるかに簡単です入力バイナリシーケンスよりも出力バイナリシーケンスのほうが大きい。

    +0

    詳細な説明をいただき、ありがとうございます。したがって、base64はビットストリームの繰り返しを「難読化」しています。興味深いことに、@ msaltersは、私のデータが '/ dev/urandom'から' xz'データを与えると、(期待どおりに)全く圧縮せず、 '/ dev/urandom'から 'base64'までは〜77%に圧縮され、ハフマン符号化によって理論上の最大値の75%に非常に近くなります。 –

    +0

    はい、ハフマン符号化を実装しているアルゴリズムは、Base64でエンコードされた文字列で256シンボル(この場合はバイト)のうちの64シンボルしか使用されないことを確認します。ランダムデータの場合、すべての64個のシンボルは一様な分布を得なければならず、したがって圧縮率は〜75%になります。 – Arnauld

    +0

    に1を加えて "すべてのアルゴリズムは今言っている:"それはどんな混乱ですか? " – user305883

    関連する問題