▽zipファイルの操作

zlibを利用してzip形式のファイルを直接操作するクラスを作ってみました。

ソースコードはこちら。

zipファイルの圧縮・展開サンプルプログラム
sk02-18.lzh

skLib ver 1.0 [018]
sklib-018.lzh

サンプルプログラムはskLibを使用しています。ソースコードをコンパイルする際はあらかじめ、skLibの環境を整えておいてください。

○使用方法

今回のサンプルプログラムは以下の機能を持っています。

・ドロップされたファイルの圧縮
ビューにドロップされたファイル・フォルダをまとめてzipファイルに圧縮します。あらかじめ、圧縮したファイルの出力先をメニューの[zip] - [出力先を指定]で指定しておいてください。
圧縮を行うときのファイルの取り扱い方法についてはメニューの[圧縮方法]で選択する事ができます。それぞれ、内部的にどのような処理がされているかは後述します。
・ドロップされたzipファイルの展開
ビューにドロップされたzipファイルを展開します。圧縮の場合と同様、あらかじめ出力先を指定しておく必要があります。
展開するときのファイルの取り扱い方法についてはメニューの[展開方法]で選択する事ができます。
・リソースに持っているzipファイルからファイルの取り出し
プログラム内部にリソースとして入っているzipファイルから指定されたファイルを展開します。メニューの[リソースを展開]から取り出したいファイルを選択してください。

ドロップされたファイルをzipファイルと見なして展開するのか、それとも圧縮するのかはメニューの[zip] - [エンコード] / [zip] - [デコード]かツールバーから選択できます。

zipファイルを操作する機能のテストが目的のプログラムですから使い勝手は最悪です。というか、これ、zipファイルを操作する目的では使えないでしょう(笑)

○skZipIO

zipファイルを操作するために作ったskZipIOについて解説します。

○基本的な使い方

    virtual bool        DecodeAll( const char* arc,const char* dst );
    virtual bool        EncodeAll( const char* arc,CStringArray* all );

    virtual void        EncodeFlag( int comp = 6,bool recursive = true );

この3つの関数で簡単なファイルの圧縮・展開が行えます。

DecodeAll()は指定したzipファイル内のファイルをすべて展開する関数です。arcにzipファイルのファイル名、dstに展開先となるフォルダ名を指定します。

EncodeAll()は複数のファイルをまとめて圧縮する関数です。圧縮率・フォルダの再帰処理を変更したい場合はEncodeFlag()関数でフラグを変更しておきます。

圧縮処理ではフォルダ名も指定できます。再帰処理が有効になっていれば、自動的にフォルダ内部のファイルを圧縮してくれます。

○ファイルの個別展開

ファイルをまとめて展開する他に、個別にファイルを展開する関数も用意してあります。

    virtual bool        DecodeOpen( const char* arc );

    virtual bool        DecodeFileOne( const char* name,const char* dst );
    virtual bool        DecodeFileList( CStringArray* all );

    virtual void        DecodeClose( void );

DecodeOpen()でzipファイルをオープン、ファイル名と展開先フォルダを指定してDecodeFileOne()でファイルを展開、使い終わったらDecodeClose()でクローズします。簡単ですね。

zipファイルをオープンしている状態なら、DecodeFileList()で圧縮されているファイルの一覧を取得できます。この一覧から、特定のファイルだけを展開するような使い方も便利でしょう。たぶん。

○ファイルの順次展開

zipファイル内部の情報がわからないときなど、圧縮されているファイルを順番に処理するための関数も用意してあります。
    virtual bool        DecodeGoTop( void );
    virtual bool        DecodeGoNext( void );
    virtual bool        DecodeAtFile( const char* dst );

    virtual CString     DecodeFilename( void );
    virtual int         DecodeLength( bool comp = false );

この処理も、DecodeOpen() / DecodeClose()でのzipファイルのオープン/クローズが必要です。

zipファイルをオープンしたら、DecodeGoTop()でzipファイル内部の最初のファイルの情報を調べておきます。調べたファイル名はDecodeFilename()で、ファイルサイズはDecodeLength()で取得できます。

そのファイルを展開するときはDecodeAtFile()を呼び出します。次のファイルに処理を移すときはDecodeGoNext()です。

○ファイルの個別圧縮

ファイルを1個ずつ順番に圧縮していく事もできます。

    virtual bool        EncodeCreate( const char* arc );
    virtual bool        EncodeFileOne( const char* one,const char* base );
    virtual void        EncodeClose( void );

EncodeCreate()でzipファイルを作成し、EncodeFileOne()でファイルを圧縮。すべてのファイルを圧縮し終えたらEncodeClose()でzipファイルをクローズします。

EncodeFileOne()の引数でoneは圧縮するファイルのファイル名です。baseがちょっとわかりにくいですが、zipファイルに登録する名前を決めるときに、絶対パスから相対パスへ変換するための基準フォルダを意味します。

たとえば『C:\WINDOWS\system32\winhlp32.exe』を圧縮する場合、baseに『C:\WINDOWS\』を指定すればzipファイルに登録される名前は『system32\winhlp32.exe』になります。baseの指定が『C:\WINDOWS\system32\』なら、zipファイルに登録される名前は『winhlp32.exe』になります。

○ストリーム経由の処理

skZipIOではzipファイルのかわりにストリームを使う事ができるように設計してあります。

    virtual bool        DecodeAll( CFile* arc,const char* dst );
    virtual bool        EncodeAll( CFile* arc,CStringArray* all );

    virtual bool        DecodeOpen( CFile* arc );
    virtual bool        EncodeCreate( CFile* arc );

引数にCFileを使っている所が、ストリーム処理される部分です。CFileの派生クラスなら何でも使えますから、たとえば、CMemFileを使えばメモリ上のzipファイル、CSocketを使えばネット上のzipファイルを操作できます。

もちろん、zipファイルだけじゃなく圧縮元になるファイル・展開先のファイルもストリームに置き換える事ができます。

    virtual bool        DecodeFileOne( const char* name,CFile* dst );
    virtual bool        DecodeAtFile( CFile* dst );

    virtual bool        EncodeFileOne( CFile* one,const char* name );

このあたりを組み合わせて使えば、メモリ上のzipファイルから、直接、メモリにファイルを展開したりできます。

○注意点

ストリーム処理については、すべてのCFileの派生クラスで問題なく動作するかどうかはわかりません。

理論的には大丈夫なはずですが・・・ 個人的には、そこまでMFCを信用しきれない気が。変わった使い方をするときは、事前に、十分テストしてからにしましょう。

skZipIOの他にもskLibにクラスが追加されてますが・・・ まぁ、詳しい使い方はソースを参照という事で。

(´-`).。о〇(最大の疑問点は、CFile系列のクラスを使った処理をストリーム処理といえるのかどうかだな・・・)


[skLib] Presented by See.Ku [2005/2/1]