libbzip2 の使い方

矢田 晋

Abstract: libbzip2 は bzip2 で採用されている圧縮アルゴリズムのライブラリです.Burrows-Wheeler Transform (BWT) を用いることが特徴の一つであり,gzip と比較すると,圧縮・伸長には時間がかかるものの,優れた圧縮率を示すことが多くなります.本記事は,C 言語から libbzip2 を利用する方法の解説になっています.

はじめに

libbzip2 のマニュアル公式サイトで提供されています.

libbzip2 では,bz_stream という構造体を用いる低水準インタフェースと,BZFILE という型を用いる高水準インタフェースが用意されています.低水準インタフェースはメモリ上で圧縮・伸長をおこなうためのインタフェースであり,高水準インタフェースは bzip2 形式のファイルを読み書きするためのインタフェースになっています.

以下,libbzip2 のインストール方法を紹介した後,メモリ上での圧縮・伸長bzip2 形式のファイルを操作する関数群について説明します.また,libbzip2 を用いて圧縮・伸長をおこなうプログラムのサンプルコードを用意しました.

インストール

Debian 系の環境における開発用パッケージのインストール

$ sudo aptitude install libbz2-dev
$ sudo apt-get install libbz2-dev

Debian 系の環境であれば,aptitude を使って簡単にインストールできます.インストールには root 権限が必要なので,必要に応じて sudosu を使ってください.古い環境であれば,apt-get になるかもしれません.

Red Hat 系の環境における開発用パッケージのインストール

$ sudo yum install bzip2-devel

Red Hat や CentOS であれば,yum を使って簡単にインストールできます.こちらも必要に応じて sudosu を使ってください.

SUSE Linux 系の環境における開発用パッケージのインストール

$ zypper install libbz2-devel

openSUSE では zypper を使ってインストールできるようです.必要に応じて su を使ってください.

ソースコードからのインストール

$ wget http://www.bzip.org/1.0.6/bzip2-1.0.6.tar.gz
$ tar zxf bzip2-1.0.6.tar.gz
$ cd bzip2-1.0.6
$ make
$ sudo make install

ソースコードの tarball は公式サイトのダウンロードページからダウンロードできます.ブラウザや wget により tarball をダウンロードした後は,make, make install という一手順でインストールします.libbzip2 を軽く試してみるのであれば,make まで終わった時点で,bzlib.h, libbz2.a のみをコピーして使うことも可能です.

インストールの確認

// test.c
#include <bzlib.h>
int main(void) {
  bz_stream strm = { .bzalloc = NULL, .bzfree = NULL, .opaque = NULL };
  BZ2_bzCompressInit(&strm, 9, 0, 0);
  BZ2_bzCompressEnd(&strm);
  return 0;
}
$ gcc -Wall -std=c99 test.c -lbz2

簡単なソースコードをコンパイル・リンクしてみれば,libbzip2 が問題なくインストールされているかどうか分かります.リンクにおいては,libbzip2 を指定するオプション(-lbz2)が必要になります.

サンプルは C 言語のコードになっています.gcc では問題なくコンパイルできますが,g++ ではエラーになるのでご注意ください.strm の初期化コードが気になる方は,プログラミング言語 C の新機能をご覧ください.

圧縮・伸長

圧縮・伸長の概要

typedef struct {
  char *next_in;                // 入力位置
  unsigned int avail_in;        // 入力データの残りバイト数
  unsigned int total_in_lo32;   // 入力データの合計バイト数(下位 32 ビット)
  unsigned int total_in_hi32;   // 入力データの合計バイト数(上位 32 ビット)

  char *next_out;               // 出力位置
  unsigned int avail_out;       // 出力バッファの残りバイト数
  unsigned int total_out_lo32;  // 出力データの合計バイト数(下位 32 ビット)
  unsigned int total_out_hi32;  // 出力データの合計バイト数(上位 32 ビット)

  void *state;                  // 内部状態

  void *(*bzalloc)(void *, int, int);  // メモリの確保に用いる関数
  void (*bzfree)(void *, void *);      // メモリの解放に用いる関数
  void *opaque;                        // bzalloc と bzfree に渡すポインタ
} bz_stream;
z_stream strm;
strm.bzalloc = NULL;
strm.bzfree = NULL;
strm.opaque = NULL;

libbzip2 による圧縮・伸長では,bz_stream という構造体を利用することになります.bz_stream の役割は zlib における z_stream に相当し,オブジェクトを作成した直後に,bzalloc, bzfree, opaque を設定しておく必要があります.bzalloc, bzfree にはメモリの確保・解放に用いる関数のポインタ,opaque には引数を指定できるようになっていますが,基本的に使い方では,デフォルトの設定となる NULL を代入しておけば問題ありません.

bz_stream のオブジェクトを初期化した後は,圧縮する場合と伸長する場合とで呼び出すべき関数が異なります.圧縮する場合は,BZ2_bzCompressInit() で初期設定,BZ2_bzCompress() で圧縮,BZ2_bzCompressEnd() で終了処理となります.伸長する場合は,BZ2_bzDecompressInit() で初期設定,BZ2_bzDecompress() で伸長,BZ2_bzDecompressEnd() で終了処理となります.

圧縮前後のデータをすべてメモリ上に展開できるときや,メモリマップト I/O によりファイル全体をメモリ上にマップできるときなど,データをひとまとめにして圧縮できる状況では,BZ2_bzBuffToBuffCompress() を使って一息に圧縮することが可能です.同様に,BZ2_bzBuffToBuffDecompress() を使って一息に伸長することも可能です.これらの関数を用いる場合,bz_stream は不要になります.

圧縮

int BZ2_bzCompressInit(bz_stream *strm,
                       int blockSize100k,
                       int verbosity,
                       int workFactor);
int ret = BZ2_bzCompressInit(&strm, 9, 0, 0);
assert(ret == BZ_OK);

圧縮の初期設定には BZ2_bzCompressInit() を使います.第 1 引数である strm は,bzalloc, bzfree, opaque を設定した bz_stream のオブジェクトを受け取るようになっています.第 2 引数である blockSize100kには,圧縮に用いるブロックサイズを指定するようになっています,ブロックサイズは 100,000 単位であり,指定できる値の範囲は 1 以上 9 以下です.おおよそのメモリ消費は (4 + (8 x blockSize100k)) x 100kB により算出できます.標準的なコマンドである bzip2 が用いるデフォルトのブロックサイズは 9 であり,最も良い圧縮率を示す設定になっています.新しい PC は大容量のメモリを搭載しているので,特段の理由がない限り,9 で問題ないと思います.次に,第 3 引数である verbose には 0 以上 4 以下の値を指定するようになっています.0 のときは静かにしていますが,値を大きくするにしたがって徐々に小煩くなります.デバッグに有用なオプションです.最後に,第 4 引数である workFactor には,標準のアルゴリズムで上手くソートできないときの振る舞いを指定するようになっています.指定できる値の範囲は 0 以上 250 以下であり,大きいほど標準のアルゴリズムで粘ります.ただし,0 のときはデフォルトの設定である 30 を使うようになっています.BZ2_bzCompressInit() は成功すると BZ_OK を返し,失敗すると BZ_CONFIG_ERROR, BZ_PARAM_ERROR, BZ_MEM_ERROR のいずれかを返します.

int BZ2_bzCompress(bz_stream *strm, int action);
int action = BZ_RUN;
int ret = BZ_OK;
do {
  strm.next_in = (char *)...;
  strm.avail_in = ...;
  if (/* 入力が尽きていれば */) {
    action = BZ_FINISH;
  }
  do {
    strm.next_out = (char *)...;
    strm.avail_out = ...;
    ret = BZ2_bzCompress(&strm, action);
    assert(ret != BZ_SEQUENCE_ERROR);
    // 出力バッファの中身を処理
  } while (strm.avail_out == 0);
  assert(strm.avail_in == 0);
} while (action != BZ_FINISH);
assert(ret == BZ_STREAM_END);

圧縮には BZ2_bzCompress() を使います.第 1 引数には入力データと出力バッファを設定した bz_stream のオブジェクト,第 2 引数には BZ_RUN を指定します.ただし,すべての入力データを指定した後は,圧縮を完了させるために BZ_FINISH を指定します.また,BZ_FLUSH を指定することにより,圧縮中のブロックを打ち切って出力を強制することも可能ですが,この機能を使う機会は少ないと思います.

入力データの設定については,bz_stream のメンバである next_in, avail_in に対しておこないます.出力バッファの設定については,bz_stream のメンバである next_out, avail_out に対しておこないます.BZ2_bzCompress() を呼び出すときは,avail_out0 にならないように注意してください.なお,next_in, next_outchar のポインタになっているので,明示的に型変換しないとコンパイラに警告されるかもしれません.

BZ2_bzCompress() の第 2 引数と返り値の関係
第 2 引数返り値
BZ_RUN BZ_RUN_OK
BZ_FLUSH BZ_RUN_OK, BZ_FLUSH_OK
BZ_FINISH BZ_FINISH_OK, BZ_STREAM_END

BZ2_bzCompress() の返り値は,bz_stream の内部状態を示すものとエラーを示すものに分けることができます.内部状態を示す返り値は BZ_RUN_OK, BZ_FLUSH_OK, BZ_FINISH_OK, BZ_STREAM_END の 4 種類であり,次に取るべき行動を示しています.BZ_STREAM_END 以外については,圧縮が継続していることを示しているので,続けて BZ2_bzCompress() を呼び出すことになります.ただし,返り値が BZ_FLUSH_OK のときは,BZ_RUN_OK が返されるまで, BZ_FLUSH を第 2 引数として呼び出し続ける必要があります.また,BZ_FINISH_OK のときは,BZ_STREAM_END が返されるまで BZ_FINISH を第 2 引数として呼び出すことになります.BZ_STREAM_END は圧縮が完了したことを示しています.エラーを示す返り値は BZ_PARAM_ERROR, BZ_SEQUENCE_ERROR の 2 種類であり,引数が NULL の場合や内部状態と第 2 引数が合っていない場合など,プログラムに問題があることを意味します.

BZ2_bzCompressEnd(&strm);

BZ2_bzCompressInit() で初期設定をおこなった bz_stream のオブジェクトについては,BZ2_bzCompressEnd() を使って,内部状態に割り当てられたメモリを解放する必要があります.zlib とは異なり,圧縮が完了していない状態で呼び出しても BZ_OK を返すようになっています.

伸長

int BZ2_bzDecompressInit(bz_stream *strm,
                         int verbosity,
                         int small);
int ret = BZ2_bzDecompressInit(&strm, 0, 0);
assert(ret == BZ_OK);

伸長の初期設定には BZ2_bzDecompressInit() を使います.第 1 引数である strm は,bzalloc, bzfree, opaque を設定した bz_stream のオブジェクトを受け取るようになっています.zlib とは異なり,next_in, avail_in を設定しておく必要はありません.第 2 引数である verbose には 0 以上 4 以下の値を指定するようになっています.0 のときは静かにしていますが,値を大きくするにしたがって徐々に小煩くなります.デバッグに有用なオプションです.第 3 引数である small により,伸長に用いるアルゴリズムを選択できるようになっています.small0 以外の値であれば,時間がかかる代わりにメモリ消費を抑えるアルゴリズムを使用します.伸長に必要なメモリは,small0 のときは (1 + (4 x blockSize100k)) x 100kB 程度,0 以外のときは (1 + (2.5 x blockSize100k)) x 100kB 程度になります.BZ2_bzDecompressInit() は成功すると BZ_OK を返し,失敗すると BZ_CONFIG_ERROR, BZ_PARAM_ERROR, BZ_MEM_ERROR のいずれかを返します.

int ret = BZ_OK;
do {
  strm.next_in = (char *)...;
  strm.avail_in = ...;
  assert(strm.avail_in != 0);
  do {
    strm.next_out = (char *)...;
    strm.avail_out = ...;
    ret = BZ2_bzDecompress(&strm);
    assert((ret == BZ_OK) ||
           (ret == BZ_STREAM_END));
    // 出力バッファの中身を処理
  } while (strm.avail_out == 0);
} while (ret != BZ_STREAM_END);

初期設定の後は,入力データと出力バッファを設定した bz_stream のオブジェクトを引数として BZ2_bzDecompress() を呼び出し,伸長をおこないます.入出力の設定方法は,圧縮されたデータが入力となり,伸長されたデータが出力となることを除けば,圧縮の場合と同じです.next_in, avail_in に入力データ,next_out, avail_out に出力バッファを設定します.BZ2_bzCompress() を呼び出すときと同様に,avail_out0 にならないように注意してください.

BZ2_bzDecompress() の返り値は,BZ_OK, BZ_STREAM_END, BZ_PARAM_ERROR, BZ_DATA_ERROR, BZ_DATA_ERROR_MAGIC, Z_MEM_ERROR の 6 種類です.伸長が問題なく継続していれば BZ_OK,無事に完了すれば BZ_STREAM_END になります.strmNULL の場合や,strm->avail_in0 の場合など,引数が明らかに異常なときは BZ_PARAM_ERROR が返り値になります.BZ_DATA_ERROR, BZ_DATA_ERROR_MAGIC は入力データが bzip2 形式に適合しないことを示し,Z_MEM_ERROR はメモリの確保に失敗したことを示します.

int BZ2_bzDecompressEnd(bz_stream *strm);

BZ2_bzDecompressInit() で初期設定をおこなった bz_stream のオブジェクトについては,BZ2_bzDecompressEnd() を使って,内部状態に割り当てられたメモリを解放する必要があります.

一括圧縮・一括伸長

int BZ2_bzBuffToBuffCompress(char *dest,
                             unsigned int *destLen,
                             char *source,
                             unsigned int sourceLen,
                             int blockSize100k,
                             int verbosity,
                             int workFactor);
unsigned destLen = sourceLen + (sourceLen / 100) + 600;
char *dest = (char *)malloc(destLen);
assert(dest != NULL);
int ret = BZ2_bzBuffToBuffCompress(
    dest, destLen, source, sourceLen, 9, 0, 0);
assert(ret == BZ_OK);

bz_stream を介することなく一息に圧縮をおこなうインタフェースとして,BZ2_bzBuffToBuffCompress() という関数が用意されています.入力データと出力バッファをそれぞれ連続空間に配置できる状況に限られますが,とても簡単に圧縮できるという利点があります.圧縮後のデータが確実に収まる出力バッファのサイズは,入力データのサイズ x 1.01 + 600bytes により算出されます.

BZ2_bzBuffToBuffCompress() は,第 1 引数,第 2 引数として出力バッファを受け取り,第 3 引数,第 4 引数として入力データを受け取るようになっています.圧縮が成功したときは,第 2 引数である destLen の参照先に出力データのサイズが格納されます.第 5 引数から第 7 引数までは,BZ2_bzCompressInit() の第 2 引数から第 4 引数までと同じ意味を持っています.BZ2_bzBuffToBuffCompress() の返り値は,BZ2_bzCompressInit() が持つ 4 種類の返り値に対して,出力バッファのサイズ不足を意味する BZ_OUTBUFF_FULL を加えた 5 種類になります.

int BZ2_bzBuffToBuffDecompress(char *dest,
                               unsigned int *destLen,
                               char *source,
                               unsigned int sourceLen,
                               int small,
                               int verbosity);

伸長には BZ2_bzBuffToBuffDecompress() を使います.BZ2_bzBuffToBuffCompress() と同様に,第 4 引数までは出力バッファと入力データを受け取るという役割を持っており,第 5 引数以降は BZ2_bzDecompressInit() の第 2 引数以降と同じ意味を持っています.入力データのサイズから出力バッファに割り当てるべきサイズを正確に求めることは難しいので,圧縮の段階で元のサイズを保存しておくのが確実です.BZ2_bzBuffToBuffDecompress() の返り値は,BZ2_bzDecompressInit(), BZ2_bzDecompress() が持つ 7 種類の返り値に対して,出力バッファのサイズ不足を意味する BZ_OUTBUFF_FULL を加えた 8 種類になります.

ファイル操作

ファイル操作の概要

typedef void BZFILE;

libbzip2 には bzip2 形式のファイルを操作するための高水準インタフェースが用意されています.主要な構成は,ファイルのハンドルとして使われる BZFILE *,読み込み用の関数群である BZ2_bzRead*(),書き込み用の関数群である BZ2_bzWrite*() です.これらの関数には,第 1 引数である bzerror の参照先にエラー番号を格納するという共通点があります.関数を呼び出した後は,このエラー番号がにより成否を確認するようになっています.BZ_OK は成功,BZ_OK 以外は失敗を意味します.また,エラー番号が BZ_IO_ERROR のときは,errnoperror(), strerror() を利用して,ファイル入出力に関するエラーの内容を調べることができます.

libbzip2 の高水準インタフェースは,zlib におけるファイル操作用のインタフェースと大きく異なっています.そのため,libbzip2 の高水準インタフェースを利用して gzip 形式から bzip2 形式へと移行しようとすると,かなりの手間がかかります.そこで,zlib との互換性を高めるために,gzip 形式のファイルを操作する関数のいくつかに対して,代替となる関数が用意されています.ただし,まだ libbzip2 の一部として正式に採用されているわけではありません.

bzip2 形式のファイルから読み込む

BZFILE *BZ2_bzReadOpen(int *bzerror,
                       FILE *file,
                       int verbosity,
                       int small,
                       void *unused,
                       int nUnused);

BZ2_bzReadOpen は標準のファイルハンドルである FILE * を libbzip2 のファイルハンドルに相当する BZFILE * に関連付ける関数です.第 2 引数である file を関連付けた BZFILE * を返すようになっています.第 3 引数の verbosity と第 4 引数の small は,BZ2_bzDecompressInit() における同名の引数と同じ意味を持っています.

残る引数である unused, nUnused は,file からの読み込みより前に入力するデータを受け取るために用意されています.入力できるデータの大きさは最大で BZ_MAX_UNUSED バイトです.ブロック単位のファイル読み込みなどにより,圧縮されたデータの先頭がメモリ上に展開されている状況において有用です.想定されている用途は,BZ2_bzReadGetUnused() により受け取ったデータの入力です.入力がないときは,unusedNULLnUnused0 を渡してください.

int BZ2_bzRead(int *bzerror,
               BZFILE *bzfile,
               void *buf,
               int len);

BZ2_bzRead() は,第 2 引数である bzfile から,第 3 引数である buf を始点とする出力バッファに,第 4 引数である len を長さの上限としてデータを読み込む関数です.実際に読み込まれたデータの長さが返り値になります.長さは byte 単位です.圧縮されたデータの終端に到達したときや,ファイルの読み込みにおいてエラーが起きたときなど,返り値が len より小さくなることがあります.

void BZ2_bzReadGetUnused(int *bzerror,
                         BZFILE *bzfile,
                         void **unused,
                         int *nUnused);

BZ2_bzRead() はブロック単位でファイルからの読み込みをおこなうため,圧縮されたデータの後に別のデータが保存されている場合,圧縮されたデータの終端を越えて読み込んでしまうことがあります.そのため,BZ2_bzRead() により bzerror の参照先が BZ_SEQUENCE_END で上書きされた後,BZ2_bzReadClose() を呼び出す前に,読み込み過ぎたデータをBZ2_bzReadGetUnused() によって取り出せるようになっています.

void BZ2_bzReadClose(int *bzerror,
                     BZFILE *bzfile);

BZ2_bzReadClose() は,第 2 引数の bzfile を閉じる関数です.bzfile に関連付けられていたファイルハンドルについては,呼び出し側で閉じる必要があります.必要に応じて,fclose()pclose() により閉じてください.

bzip2 形式のファイルに書き込む

BZFILE *BZ2_bzWriteOpen(int *bzerror,
                        FILE *file,
                        int blockSize100k,
                        int verbosity,
                        int workFactor);

BZ2_bzWriteOpen は標準のファイルハンドルである FILE * を libbzip2 のファイルハンドルに相当する BZFILE * に関連付ける関数です.第 2 引数である file を関連付けた BZFILE * を返すようになっています.残りの引数は,BZ2_bzCompressInit() における同名の引数と同じ意味を持っています.

void BZ2_bzWrite(int *bzerror,
                 BZFILE *bzfile,
                 void *buf,
                 int len);

BZ2_bzWrite() は,第 2 引数である bzfile に対して,第 3 引数と第 4 引数である buflen により与えられる入力データを書き込む関数です.書き込みの成否は,bzerror によってのみ確認できます.

void BZ2_bzWriteClose(int *bzerror,
                      BZFILE* bzfile,
                      int abandon,
                      unsigned int* nbytes_in,
                      unsigned int* nbytes_out);
void BZ2_bzWriteClose64(int *bzerror,
                        BZFILE* bzfile,
                        int abandon,
                        unsigned int *nbytes_in_lo32,
                        unsigned int *nbytes_in_hi32,
                        unsigned int *nbytes_out_lo32,
                        unsigned int *nbytes_out_hi32);

BZ2_bzWriteClose()BZ2_bzWriteClose64() は,第 2 引数である bzfile に対して,内部状態として保持しているデータを圧縮し,その結果をファイルに書き込むことと,メモリの解放を指示する関数です.ただし,第 3 引数である abandon0 でないときは,圧縮や書き込みを省略し,メモリの解放のみを指示します.残る引数である nbytes_in, nbytes_out およびに nbytes_in_lo32, nbytes_in_hi32, nbytes_out_lo32, nbytes_out_hi32NULL でないときは,参照先が入出力の合計バイト数によって上書きされます.

zlib との互換性を高めるためのインタフェース

libbzip2, zlib, 標準ライブラリにおける関数の対応
libbzip2 zlib 標準ライブラリ
BZ2_bzopen() gzopen() fopen()
BZ2_bzdopen() gzdopen() fdopen()
BZ2_bzclose() gzclose() fclose()
BZ2_bzread() gzread() fread()
BZ2_bzwrite() gzwrite() fwrite()
BZ2_bzflush() gzflush() fflush()
BZ2_bzerror() gzerror() ferror()
BZFILE *BZ2_bzopen(const char *path, const char *mode);
BZFILE *BZ2_bzdopen(int fd, const char *mode);
void BZ2_bzclose(BZFILE* b);

libbzip2 の高水準インタフェースだけでは zlib から libbzip2 への移行が難しいので,zlib との互換性を高めるために,gzip 形式のファイルを操作する関数のいくつかに対して,代替となる関数が用意されています.ただし,まだ libbzip2 の一部として正式に採用されているわけではありません.ドキュメントにも仕様が明示されていないので,以下の説明は間違っているかもしれません.

BZ2_bzopen() によりファイルを開くことができます.fopen() と同様に,第 1 引数にファイル名,第 2 引数にモードを指定するようになっています.ただし,読み書き両用を示す + を指定することはできません.また,書き込み用にファイルを開く場合,gzopen() における圧縮レベルの代わりに,ブロックサイズを 1 以上 9 以下の数字によって指定できます.返り値の型は BZFILE * であり,ファイルを開くことができれば,NULL 以外の値になります.このハンドルは以降の操作に必要であり,操作の後で BZ2_bzclose() を使って閉じる必要があります.

既に開いているファイル記述子があれば,BZ2_bzdopen() により BZFILE * と関連付けることができます.fdopen() と同様に,第 1 引数にファイル記述子,第 2 引数にモードを指定するようになっています.また,BZ2_bzdopen() と同様に,+ の指定ができない代わりに,ブロックサイズ(19)の指定ができるようになっています.BZ2_bzclose() は関連付けられたファイル記述子も閉じるので,ファイル記述子を閉じずに残しておきたいときは,dup() などを使って複製しておくようにしてください.

BZ2_bzopen(), BZ2_bzdopen() により作成したファイルハンドルは,BZ2_bzclose() を使って閉じる必要があります.書き込み用のファイルについては,内部状態として保持されているデータをファイルに書き込んでから閉じるようになっています.

int BZ2_bzread(BZFILE* b, void* buf, int len);

BZ2_bzread() は,第 2 引数の buf と第 3 引数である len によって与えられる出力バッファにデータを読み込む関数です.gzread(), fread() に対応する関数ですが,整数の型が int に統一されていることや,サイズを指定する引数が統合されているという違いがあります.ファイルの終端とエラーを区別するかどうかは不明です.

int BZ2_bzwrite(BZFILE* b, void* buf, int len);
int BZ2_bzflush(BZFILE* b);

BZ2_bzwrite() は,第 2 引数の buf と第 3 引数である len によって与えられる入力データをファイルに書き込む関数です.gzwrite(), fwrite() に対応する関数ですが,整数の型が int に統一されていることや,サイズを指定する引数が統合されているという違いがあります.BZ2_bzflush() は何もしません.

const char *BZ2_bzerror(BZFILE *b, int *errnum);

BZ2_bzerror() は,エラー番号を第 2 引数である errnum の参照先に上書きし,エラーメッセージを返すようになっています.ただし,エラーがファイルの操作に起因する場合,エラー番号は BZ_IO_ERROR になり,エラーの詳細は errnoperror() で確認する必要があります.

サンプルコード

$ gcc -Wall -O2 -std=c99 libbzip2-test.c -lbz2 -o libbzip2-test

bzip2 形式の圧縮・伸長をおこなうプログラムのサンプルコードとして libbzip2-test.c を用意しました.C99 の機能を使っているので,gcc には -std=c99 を渡すようにしてください.

$ ./libbzip2-test --help
Usage: ./libbzip2-test [OPTION]... [FILE]...
Version: libbzip2-1.0.6, 6-Sept-2010
Options:
  -c, --compress         圧縮します (default)
  -d, --decompress       伸長します
  -b, --blocksize100k=[1-9]  ブロックサイズを指定します (default: 9)
  -w, --workfactor=[0-250]   代替アルゴリズムに切り替えるまでの
                             頑張り具合を指定します (default: 30)
  -s, --small            伸長時にメモリ消費の少ないアルゴリズムを使います
  -o, --output=[FILE]    出力ファイルを指定します (default: stdout)
  -v, --verbosity=[0-4]  詳細な情報を表示するようにします (default: 0)
  -h, --help             このヘルプを表示します

コマンドライン引数による圧縮形式や圧縮レベルの切り替えが可能になっています.-h もしくは -help をオプションとして渡すことにより,libbzip2 のバージョンとコマンドライン引数の一覧を確認することができます.

おわりに

本記事では libbzip2 の基本的な使い方を説明しました.大抵のアプリケーションについては対処できるようになっています.より高度な使い方については,公式サイトのドキュメントを参照してください.