![]() |
次のプログラムはファイル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
()の呼び出しを忘れると、フッタ情報のない不正なアーカイブができてしまうので注意すること。
今度は、先ほど作成した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
()を呼び出すことで、ヘッダ情報を取得することもできる。ここでは、ヘッダから取得したパス名と同名のファイルを作成し、エントリから読み出した内容を書き出している。
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 |