Windows でも意外と役立つ gzip 圧縮を C# から使う

gzip といっても Windows ではなじみがない人が多いでしょう。
しかし、 gzip は意外と使えるヤツです。 しかも .NET では gzip の 圧縮、展開を行うのに便利なクラスが用意されています。
そこで今回は Windows でも意外と役に立つことを紹介した後、 C# での gzip の圧縮、展開方法を説明したいと思います。

gzip とは

gzip は GNU ZIP の略で、 gzip という圧縮コマンドやその圧縮方式(圧縮後の拡張子は .gz) を指します。 Unix 系ではよく使われている圧縮方式です。
一方 Windows では ZIP がよく利用されています。 gzip と ZIP はともに Deflate という圧縮アルゴリズムを使用します。 ただし、ZIP は複数ファイルをまとめる機能を持っているのに対して、 gzip は単にデータ(ファイル)を圧縮するためのものです。 このため、ファイルをまとめる機能を持つ tar と合わせて(.tar.gz、 .tgz)使用されることが多いです。

なお、 .NET 4.5 であれば、 ZIP の圧縮、展開も対応したらしいです。 ただし、 私の場合は Windows 7 、 .NET 4.5 、 VS2012 Express の環境でやっていみたのですが、 ZIP 用のクラスは使えませんでした。

gzip の用途

先ほどの説明だと単に gzip の機能が ZIP に比べて劣っているという印象を受けた人もいるかもしれません。 確かに ZIP は便利だし、よく使われていますが、 シンプルなものにはシンプルなりの用途があります。

通信データの圧縮

gzip コマンドを使ったことがないという人は多いかもしれませんが、 実はかなりの人が知らない間に gzip 圧縮を利用しています。
というのも、見かけ上はわからないようになっていますが、 HTTP 通信で gzip 形式の圧縮がよく使われているためです。

使われる場合は次のような手順です。
  1. サーバー上には *.html.gz, *.css.gz といった圧縮したファイルを置く
  2. ブラウザーが対応していれば、 圧縮されたまま通信 (最近のブラウザーはほとんど対応)
    • 対応してない場合はサーバーで展開
  3. ブラウザー側で展開して表示
HTTP 通信に限らず、 マシンパワーはあるのに通信が細いということはよくあります。 gzip はこういった場合の 通信データの圧縮 に役に立ちます。
通信相手が Windows でない場合でも、そちらは zlib などを使えば、 圧縮、展開は結構簡単に実装できます。

ファイルフォーマット

アプリケーションを作成した場合などで、独自フォーマットのファイルを作ることはあるでしょう。
この時、陥りやすいトラップが "ビットレベルで詰めたら、サイズが得になっていいのではないか" という考え方です。
これは間違いではないのですが、実装がかなり大変になる上に、 たいていは効果も薄いです。

それをやるくらいなら、作りやすいフォーマットにして、全体または部分的にデータを圧縮した方が、 作成者にも使用者にも嬉しいフォーマットになります。
実際に svgz や PNG などでは、そうやって gzip(Deflate) が使われています。

使用クラス

データ圧縮、展開用のクラスとしては DeflateStream と GZipStream の 2 つのクラスがあります。 gzip クラス


gzip も Deflate アルゴリズムなので、 DeflateStream と GZipStream はほとんど同じものです。
ただし、 GZipStream の方が 2 つ利点があります。
  • データ破損を検出するための巡回冗長検査 (CRC) 値を含んでいる
  • 拡張して Deflate 以外のアルゴリズムに変更することができる
GZipStream クラスは Stream という名前の通り、 IO Stream のような使い方ができます。
これをフィルターのように入出力のストリームの間にかませることによって、 圧縮・展開を行うことができます。

ちなみに Unix でも gzip コマンドはフィルターとしてよく使われています。

実装

引数に渡すファイルによって次のような動作するコマンドラインプログラムをサンプルとして作ってみました。
引数 動作
.gz で終わるファイル 展開
.gz 以外のファイル 圧縮

ソースファイル : コンパイル:
 > csc GZipSample.cs
実行結果 :
~/cs/gzip $ ./GZipSample.exe sample.txt 
Input      : sample.txt
Compress   : sample.txt.gz
~/cs/gzip $ ls
GZipSample.cs  GZipSample.exe  sample.txt  sample.txt.gz
~/cs/gzip $ rm sample.txt
~/cs/gzip $ ls
GZipSample.cs  GZipSample.exe  sample.txt.gz
~/cs/gzip $ ./GZipSample.exe sample.txt.gz 
Input      : sample.txt.gz
Decompress : sample.txt
~/cs/gzip $ ls
GZipSample.cs  GZipSample.exe  sample.txt  sample.txt.gz

以下に圧縮、展開の処理部分を GZipStream.cs から抜粋したものをあげます。
なお、 using に関して詳しく知りたい方は次の記事を参考にしてください。 圧縮 :
public static void GZipCompress(string srcpath, string gzpath)
{
    // 入力用ストリーム
    using (FileStream fin = new FileStream(srcpath, FileMode.Open, FileAccess.Read, FileShare.Read))
    {
        // 出力用ストリーム
        using (FileStream fout = File.Create(gzpath))
        {
            // 出力用ストリームに gzip ストリームのフィルターを付ける
            using (GZipStream gzout = new GZipStream(fout, CompressionMode.Compress))
            {
                fin.CopyTo(gzout);
            }
        }
    }       
}
展開 :
public static void GZipDecompress(string gzpath, string destpath)
{
    // 入力用ストリーム
    using (FileStream fin = new FileStream(gzpath, FileMode.Open, FileAccess.Read, FileShare.Read))
    {
        // 出力用ストリーム
        using (FileStream fout = File.Create(destpath))
        {
            // 入力用ストリームに gzip ストリームのフィルターを付ける
            using (GZipStream gzin = new GZipStream(fin, CompressionMode.Decompress))
            {
                gzin.CopyTo(fout);
            }
        }
    }       
}
GZipStream はストリームとして実装されているのが、よくできている点だと思います。
サンプルではファイルのストリームでしたが、 Stream を継承したクラスであれば、同じようにフィルターとして使うことができます。

通信部分をNetworkStream クラスを使って実装していれば、 圧縮したデータによる通信機能も簡単に追加することができるのではないかと思います。


関連記事
スポンサーサイト
Prev.    Category    Next 

Facebook コメント


コメント

コメントの投稿

Font & Icon
非公開コメント

このページをシェア
アクセスカウンター
アクセスランキング
[ジャンルランキング]
コンピュータ
24位
アクセスランキングを見る>>

[サブジャンルランキング]
プログラミング
3位
アクセスランキングを見る>>
カレンダー(アーカイブ)
プルダウン 降順 昇順 年別

02月 | 2017年03月 | 03月
- - - 1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31 -


はてな新着記事
はてな人気記事
ブロとも申請フォーム
プロフィール

yohshiy

Author:yohshiy
職業プログラマー。
仕事は主に C++ ですが、軽い言語マニアなので、色々使っています。

はてブ:yohshiy のブックマーク
Twitter:@yohshiy

サイト紹介
プログラミング好きのブログです。プログラミング関連の話題や公開ソフトの開発記などを雑多に書いてます。ただ、たまに英語やネット系の話になることも。