|
次のプログラムはファイル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 |