## チュートリアル

### tarファイルの作成

次のプログラムはファイル`foo.txt`と`bar.txt`を含むtarファイル`test.tar`を作成する。

    #include <hamigaki/archivers/tar_file.hpp>
    #include <boost/filesystem/fstream.hpp>
    #include <boost/filesystem/operations.hpp>
    #include <boost/iostreams/copy.hpp>

    namespace ar = hamigaki::archivers;
    namespace fs = boost::filesystem;
    namespace io = boost::iostreams;

    void append_file(ar::tar_file_sink& tar, const fs::path& ph)
    {
        ar::tar::header head;
        head.path = ph;
        head.file_size = fs::file_size(ph);
        tar.create_entry(head);

        fs::ifstream file(ph, std::ios_base::binary);
        io::copy(file, tar);
    }

    int main()
    {
        ar::tar_file_sink tar("test.tar");

        append_file(tar, "foo.txt");
        append_file(tar, "bar.txt");

        tar.close_archive();
    }

tarファイルを作成するには、クラス`tar_file_sink`を用いる。コンストラクタの引数は、作成するtarファイルのパス名である。

アーカイブに追加する個々のファイルは(アーカイブ)エントリと呼ばれ、それぞれ個別のヘッダ情報を持つ。エントリを追加するには、適切な値を設定した構造体`tar::header`を引数にして、メンバ関数`create_entry`()を呼び出す。

`tar::header`のメンバ変数の内、`path`(ファイルのパス名)と`file_size`(ファイルサイズ)は必須項目である。それ以外のメンバに関してはドキュメントを参照せよ。

`create_entry`()を呼び出すと、アーカイブはSinkとして書き込み可能となる。

書き込みが完了したら、メンバ関数`close_archive`()でアーカイブを閉じる。アーカイブのフォーマットによっては、`close_archive`()の呼び出しを忘れると、フッタ情報のない不正なアーカイブができてしまうので注意すること。

### tarファイルの展開

今度は、先ほど作成した`test.tar`をカレントディレクトリに展開するプログラムを作成する。

    #include <hamigaki/archivers/tar_file.hpp>
    #include <boost/filesystem/fstream.hpp>
    #include <boost/iostreams/copy.hpp>

    namespace ar = hamigaki::archivers;
    namespace fs = boost::filesystem;
    namespace io = boost::iostreams;

    void extract_file(ar::tar_file_source& tar)
    {
        const ar::tar::header& head = tar.header();

        fs::ofstream file(head.path, std::ios_base::binary);
        io::copy(tar, file);
    }

    int main()
    {
        ar::tar_file_source tar("test.tar");

        while (tar.next_entry())
          extract_file(tar);
    }

tarファイルを読み込むには、クラス`tar_file_source`を用いる。コンストラクタの引数は、tarファイルのパス名である。

tarファイルのオープンに成功したら、メンバ関数`next_entry`()を呼び出し、次のエントリを確認する。この関数は未読のエントリがある場合`true`を返す。全てのエントリを読み終わり、これ以上のエントリが見つからない場合は`false`が返され、ループは終了する。

`next_entry`()の呼び出しに成功したら、アーカイブはSourceとして読み出し可能である。また、メンバ関数`header`()を呼び出すことで、ヘッダ情報を取得することもできる。ここでは、ヘッダから取得したパス名と同名のファイルを作成し、エントリから読み出した内容を書き出している。

### ZIPファイルの作成

tarファイルの作成項のプログラムをZIPフォーマット用に書き換えると、次のようになる。

    #include <hamigaki/archivers/zip_file.hpp>
    #include <boost/filesystem/fstream.hpp>
    #include <boost/filesystem/operations.hpp>
    #include <boost/iostreams/copy.hpp>

    namespace ar = hamigaki::archivers;
    namespace fs = boost::filesystem;
    namespace io = boost::iostreams;

    void append_file(ar::zip_file_sink& zip, const fs::path& ph)
    {
        ar::zip::header head;
        head.path = ph;
        head.file_size = fs::file_size(ph);
        zip.create_entry(head);

        fs::ifstream file(ph, std::ios_base::binary);
        try
        {
            io::copy(file, zip);
        }
        catch (const ar::give_up_compression&)
        {
            file.clear();
            file.seekg(0, std::ios_base::beg);
            zip.rewind_entry();
            io::copy(file, zip);
        }
    }

    int main()
    {
        ar::zip_file_sink zip("test.zip");

        append_file(zip, "foo.txt");
        append_file(zip, "bar.txt");

        zip.close_archive();
    }

ZIPファイルを作成するには、クラス`zip_file_sink`を用いる。コンストラクタの引数は、やはり、作成するzipファイルのパス名である。

ZIPフォーマットはtarフォーマットのようなアーカイバの機能に加え、ファイルを圧縮する機能を持っている。圧縮率はファイルの内容によって変化し、場合によっては元のサイズより大きくなってしまうこともある。Hamigaki.Archiversでは例外`give_up_compression`を送出することで、この状況を報告する。

`give_up_compression`が送出されたら、これを捕捉し、非圧縮で出力をやり直す必要がある。メンバ関数`rewind_entry`()はこのためのものであり、ファイルの書き込み位置をエントリの先頭に戻し、圧縮メソッドを非圧縮に設定する。`rewind_entry`()の呼び出しに成功したら、再度出力を試みることになる。

| 製作著作 © 2006-2008 Takeshi Mouri