システム開発をしている永松です。
音楽はビジュアル系が好きです。
前回はバイナリファイルについてふんわりと書かせていただきました。
これで1回目がふんわりだったとわかっただろうという内容でしたね。
さて、ファイル形式の基本については書いてしまったので、次は何を書こうかと頭を悩ませました。
正直もうこのシリーズ止めようかという考えもよぎりましたが、せめて3回ぐらいはやりたいと思い、なんとか続編を考えました。
何かないか、ちょうど良さそうなのはないか、あ、これでいこう、これなら書けるかも。
と思い立ち書いてみた結果、アフィサイトのようなタイトルが出来上がりました。
そう、今回はファイル圧縮についてふんわりと書かせていただきます。
題して、僕たちがダイエットに成功した理由です。
バイナリファイルがわかってきた皆さんとしては、理解と共に色々な謎も出てきてると思います。
その中の1つに、なんで圧縮でファイルサイズが小さくなるのか?という疑問を持たれた方も多いと思います。
そんな方たちにふんわり伝えたい、それが今回の主な趣旨となります。
ん?そんな疑問は持ってない?
あー、なんでWebページが見れるのかの方に興味が行ったんですね。
また今度ね。
1.圧縮の種類
ファイル圧縮と一言で言いいますが、大きく2種類あります。
可逆圧縮(かぎゃくあっしゅく)と不可逆圧縮(ふかぎゃくあっしゅく) です。
これ、実際に音読してみてください。
思ったより言える。
可逆圧縮は文字の通り、圧縮が出来て、戻すことが出来る(可逆)圧縮方法です。
有名なところでは、zip、gz、lzh などがあります。
対して不可逆圧縮も文字通り、圧縮は出来るが、戻すことが出来ない(不可逆)圧縮方法です。
有名なところでは、jpg、gif、png、mp3 などがあります。
この辺りはあまり圧縮したというイメージが薄いかもしれませんが、パソコンとしては圧縮になるんです。
ん?zipが元に戻ることはわかるけど、jpgだってbmpになるし、mp3だってwavになるから可逆圧縮なのでは?
と思われた方もいるかもしれませんが、これはファイル形式を戻しているだけでデータとしては戻っていないんです。
この疑問がわかるように、もう少し詳しく書いていこうと思います。
2.可逆圧縮
この方法には主に2つの方法が使われています。
例えば以下の文章を圧縮したとします。
すもももももももものうち
上の状態であれば12文字が必要となります。
これを以下のようにしてみます。
すも17のうち
こうすると7文字になり、5文字省略出来ることになります。
ちなみに急に出てきた「17」ですが、それぞれに意味があります。
「1」が何文字前からか、「7」がそれを繰り返す回数です。
つまり、「も17」は「も」が7回繰り返します という意味になります。
これを辞書式といいます。
次に、1回目で文字は数字で表されるという話をしましたが、もしもこれがUTF-8で書かれているなら、1文字に3バイト利用するため、全体で36バイトとなります。
そこで、もしも最も多く出現する「も」を1バイトに置き換えたとします。
すると、「も」は7回出現するので21バイト利用していますが、これが7バイトになります。
結果として、全体で19バイトまで小さくすることが出来ます。
このように、1つのファイルの中で出現頻度が高いもの程小さいバイトで表現してしまう、という方法をハフマン法などといいます。
ちなみにこの辺りも、バイナリファイルのヘッダ・ボディの考え方が使われています。
可逆圧縮では上の2つをいい感じに組み合わせ、さらにそれぞれのアレンジを加えて小さく圧縮します。
そのため、このルールを守れば小さくなったファイルを元に戻すことも出来る、というカラクリです。
3.不可逆圧縮
この方法の基本はデータを捨てるです。
bmpからjpgの場合、それぞれの色の境界線をぼかしてデータ捨てて小さくします。
wavからmp3の場合、人には聞こえない領域のデータを捨てて小さくします。
また、ただ単に捨てるだけではとどまらず、捨てた上に可逆圧縮のような圧縮も行います。
jpgなどの不可逆圧縮ファイルをzipなどで圧縮しても、あまりサイズが変わらないのはこのためです。
単純に考えても、データを捨てる不可逆圧縮の方が簡単ですし、可逆圧縮よりも小さく出来ます。
でも実際データが元に戻らないと色々不都合が起こります。
人間と同じように、パソコンもデータサイズのダイエットをすることは難しいです。
でもパソコンにとってのリバウンドはもっと大変なんです。
人間は簡単にリバウンドするのに・・・
こんなに簡単なのに・・・
4.実践
とは言ってもいきなりバイナリエディタ開いてってわけにもいかないので、まだわかる人が多そうなHTMLで説明してみようと思います。
ここから先はわからない人は流し読みしてください。
3回目だからもうみんな慣れてるよね!
さて、例えば以下のHTML。
<html> <head> <title>sample</title> </head> <body> <div style="font-size:12pt;color:#ff0000;border-bottom:solid 1px #000000;text-align:center;">ダイエット</div> <div style="font-size:12pt;color:#ff0000;border-bottom:solid 1px #000000;text-align:center;">ダイエット</div> <div style="font-size:12pt;color:#ff0000;border-bottom:solid 1px #000000;text-align:center;">ダイエット</div> <div style="font-size:12pt;color:#ff0000;border-bottom:solid 1px #000000;text-align:center;">ダイエット</div> <div style="font-size:12pt;color:#ff0000;border-bottom:solid 1px #000000;text-align:center;">ダイエット</div> <div style="font-size:12pt;color:#ff0000;border-bottom:solid 1px #000000;text-align:center;">ダイエット</div> <div style="font-size:12pt;color:#ff0000;border-bottom:solid 1px #000000;text-align:center;">ダイエット</div> <div style="font-size:12pt;color:#ff0000;border-bottom:solid 1px #000000;text-align:center;">ダイエット</div> <div style="font-size:12pt;color:#ff0000;border-bottom:solid 1px #000000;text-align:center;">ダイエット</div> <div style="font-size:12pt;color:#ff0000;border-bottom:solid 1px #000000;text-align:center;">ダイエット</div> <div style="font-size:12pt;color:#ff0000;border-bottom:solid 1px #000000;text-align:center;">ダイエット</div> <div style="font-size:12pt;color:#ff0000;border-bottom:solid 1px #000000;text-align:center;">ダイエット</div> <div style="font-size:12pt;color:#ff0000;border-bottom:solid 1px #000000;text-align:center;">ダイエット</div> <div style="font-size:12pt;color:#ff0000;border-bottom:solid 1px #000000;text-align:center;">ダイエット</div> <div style="font-size:12pt;color:#ff0000;border-bottom:solid 1px #000000;text-align:center;">ダイエット</div> <div style="font-size:12pt;color:#ff0000;border-bottom:solid 1px #000000;text-align:center;">ダイエット</div> <div style="font-size:12pt;color:#ff0000;border-bottom:solid 1px #000000;text-align:center;">ダイエット</div> <div style="font-size:12pt;color:#ff0000;border-bottom:solid 1px #000000;text-align:center;">ダイエット</div> <div style="font-size:12pt;color:#ff0000;border-bottom:solid 1px #000000;text-align:center;">ダイエット</div> <div style="font-size:12pt;color:#ff0000;border-bottom:solid 1px #000000;text-align:center;">ダイエット</div> </body> </html>
METAないのかよとかそういうのは一旦置いといてください。
あとダイエット中の方からしたら発狂しそうな状態ですが、そこもご容赦ください。
さて、こんなHTMLそうそう書きませんが、画像で言えばbmpに当たるのが上のHTMLです。
この状態で2,313バイトあります。
次にスタイルシートをヘッダにまとめてみましょう。
すると、以下のHTMLになります。
<html> <head> <title>sample</title> <style type="text/css"> div { font-size:12pt; color:red; border-bottom:solid 1px black; text-align:center; } </style> </head> <body> <div>ダイエット</div> <div>ダイエット</div> <div>ダイエット</div> <div>ダイエット</div> <div>ダイエット</div> <div>ダイエット</div> <div>ダイエット</div> <div>ダイエット</div> <div>ダイエット</div> <div>ダイエット</div> <div>ダイエット</div> <div>ダイエット</div> <div>ダイエット</div> <div>ダイエット</div> <div>ダイエット</div> <div>ダイエット</div> <div>ダイエット</div> <div>ダイエット</div> <div>ダイエット</div> <div>ダイエット</div> </body> </html>
もちろん実行結果は変わりませんが、ファイルサイズは697バイトになりました。
これだけで約70%近く圧縮されたことになります。
また、今の状態なら最初の状態に戻せるので、可逆圧縮の状態です。
ではこれを、さらにサイズが小さくなるように書いてみましょう。
<html><head><title>sample</title><style type="text/css">div{font-size:12pt;color:red;border-bottom:solid 1px black;text-align:center;}</style></head><body><div>ダイエット</div><div>ダイエット</div><div>ダイエット</div><div>ダイエット</div><div>ダイエット</div><div>ダイエット</div><div>ダイエット</div><div>ダイエット</div><div>ダイエット</div><div>ダイエット</div><div>ダイエット</div><div>ダイエット</div><div>ダイエット</div><div>ダイエット</div><div>ダイエット</div><div>ダイエット</div><div>ダイエット</div><div>ダイエット</div><div>ダイエット</div><div>ダイエット</div></body></html>
スペースと改行を取り除いて589バイトになりました。
これで約75%近くの圧縮になりました。
ただし、もう改行位置やスペースの位置はわからないので元のHTMLに戻すことはほぼ不可能です。
これが非可逆圧縮です。
5.まとめ
ファイルの圧縮ってダイエットに近いものがあるんだな。
なんかよーわからんけど、パソコンもダイエットがんばってんだな、ってことがふんわりわかってもらえたら今回の記事は成功かなと思っています。
また、このようにパソコン内では当然のようにバイナリデータが扱われています。
なのでパソコンと深く語り合うためには、どうしてもバイナリデータとの付き合いは避けて通れません。
ダイエットの本当の戦いはリバウンドとの戦いだ、なんてことを聞いたことがある気がしますが、人間はリバウンドしないように戦いますが、パソコンはリバウンドできるように戦います。
人間のダイエットは脂肪を捨てるわけなので、不可逆圧縮なはずなんですが、別のものでリバウンドという名の復元が出来ちゃうんですよね。
他のもので代用出来るなんて、やっぱり人間ってすごいなぁ、としみじみ思います。
いや、でも人間にとっての不可逆って足とか切っちゃうことか?
なんか急に怖い感じになってきたので、この辺りで今回の記事はおしまいにしようと思います。
おまけ:恐怖、ZIP爆弾
多くの場合、本当にすばらしいものは怖いほどシンプルなものです。
この話はパソコンにも通用します。
そのため、悪意を持つと結構簡単にえげつないことが出来ちゃったりします。
このZIP爆弾は、いくつもあるパソコンのえげつない攻撃方法の1つです。
本編で述べたように、圧縮されたzipファイルもバイナリデータなので、実際に圧縮しなくても、同じデータをバイナリエディタで記述すれば、圧縮されたzipファイルを作ることが出来るのです。
はー、なるほどなー、と関心する話なのですが、問題はここからです。
もし、1つの文字で作られたテキストファイルを圧縮したzipデータをバイナリエディタで作ったとします。
でもこのzipファイルを解凍すると1000000TBあったとすると?
ファイルの内容が単純なので、こんなえげつないファイルサイズでもzip圧縮するとめちゃ小さいサイズで作れちゃいます。
なので、こんなファイルを作って誰かに送りつけて、その方が解凍しちゃうとHDDの容量を1発で使い切ることになります。
今はパソコンがお利口さんになったのでこの攻撃でパソコンが使えなくなることはまずないですが、昔はこれでディスク容量を使い切って使えなくするなんてことが出来ました。
詳しく知りたい方はZIP爆弾で調べてみてください。
色々面白い話が乗ってたり乗ってなかったりしてます。
もちろん悪用厳禁です。
おまけ2:圧縮すればするほど小さくなる?
ISDNはじめちゃん出来なかった頃、パソコンの回線速度はスマホの低速モードより遅かったんです。
そんな頃、ネット上にはこんなネチケットが広まりました。
重いファイルを送るとき、最低3回はzip圧縮して送るのが礼儀
この頃の重いファイルといえば500kbとかなんですが、
このサイズのファイルをメール添付なんてされた日にはちょっとイラっとするぐらいメールの受信が遅くなったりしたものです。
それでも、どうしても重いファイルを送らないといけないときは、ICQやメールで事前に許可を取ったりしてたものです。
さて、昔話はさておき、実際zip圧縮は回数を多くすればするほどファイルサイズは小さくなるのでしょうか。
この疑問に答えるべく、10Mのデータを100回圧縮した結果を以下に貼ってみます。
縦軸がファイルサイズ、横軸が回数です。
このように、回数が増えれば増えるほど、ファイルサイズは増加します。
これはなぜか。
zip圧縮では、圧縮した際に実際のファイルに追加でzipファイル用のヘッダが作られます。
また、1度zip圧縮すればzipアルゴリズムで圧縮されているため、それ以上の圧縮は見込めません。
そのため、回数が増えれば増えるほど、ファイルヘッダ分の容量が増えていくため、ファイルサイズも増えるということが理由となります。
もちろん、zip、lzhなど色々な圧縮方法を組み合わせることで小さくなる可能性はありますが、そこまで小さくはなりません。
なのに回数分解凍する時間が必要となるため、この方法はあまり意味がなかったと言えるでしょう。
もうこんな噂はご存知ない方も多いと思いますが、昔はこんな噂が生まれては消えていました。
まぁ今も形を変えていろんな噂が生まれては消えていっていると思います。
皆さんはどうか、そういった噂に流されず、ちゃんと成否を確認して、正しい判断をしてくださいね。
そういえば、ネチケットって言葉も消えましたね。
永松
この記事を書いた人黙々とパソコンに向き合い、少々の無理難題にも粛々と応える、お悟りお開き系エンジニア。AND SPACEの様々なシステム案件を任されているだけでなく、会社全体の運営にも的を射た意見で常々存在感を発揮する。顧客や同僚にいくら駄々をこねられても、淡々と正論を繰り出す姿は、「ナガえもん」と呼ばれて然り。いかなるシステム案件も、最初は粗々で構わないと言い切れるのは、ユーザー目線の「実際の使用感」が大切なことを重々承知しているから。そこからの喧々諤々こそ真骨頂。皆々、度々、多々、救われる。