これを使うと、データの圧縮・解凍が簡単にできます。
・導入方法
何も考えずにダウンロード→解凍→configure→make→make installするだけの簡単なお仕事です。
【訂正】何も考えずにconfigure→make→make installするだけの簡単なお仕事ではありません。
make -f win32/Makefile.gccするだけの簡単なお仕事でした。
または、コンパイラの配布サイトでもバイナリが配布されています。
・ドキュメント
zlib 1.2.8 Manual
・ソースコード
基本の操作方法は至ってシンプル。
入力バッファがなくなったら足す。終わりなら終わりと言う。
出力バッファを投げて、データが出てきたら拾う。
それだけ。
#include
#include
int main(int argc, char *argv[]) {
Bytef input_buffer[1024];
Bytef output_buffer[1024];
z_stream stream;
int ret;
FILE* fp_in;
FILE* fp_out;
int eof_detected;
int do_inflate = 0;
int inited;
/* バージョンを出力 */
fprintf(stderr, "ZLIB_VERSION : %s\n", ZLIB_VERSION);
fprintf(stderr, "zlibVersion : %s\n", zlibVersion());
/* コマンドライン引数チェック */
if (argc 0 ? argv[0] : "zlib_test");
fprintf(stderr, "use -i to inflate (decode).\n");
return 1;
}
/* deflate(エンコード) / inflate(デコード) 切り替え */
if (argc == 4) {
if (argv[3][0] == '-' && argv[3][1] == 'i' && argv[3][2] == '\0') {
do_inflate = 1;
}
}
/* ファイルオープン */
if ((fp_in = fopen(argv[1], "rb")) == NULL) {
fprintf(stderr, "input file \"%s\" open error\n", argv[1]);
return 1;
}
if ((fp_out = fopen(argv[2], "wb")) == NULL) {
fclose(fp_in);
fprintf(stderr, "output file \"%s\" open error\n", argv[2]);
return 1;
}
/* エンコード/デコード処理 */
inited = 0;
stream.avail_in = 0;
eof_detected = 0;
for (;;) {
/* 入力を使い切ったら、次の入力を読み込む */
if (!eof_detected && stream.avail_in == 0) {
size_t read_size;
read_size = fread(input_buffer, 1, sizeof(input_buffer), fp_in);
if (read_size == 0) eof_detected = 1;
/* 次に処理するべき入力を設定する */
stream.next_in = input_buffer;
stream.avail_in = read_size;
}
/* 初期化してなければ初期化する
* (inflateInitにはnext_in, avail_inを設定しないといけない) */
if (!inited) {
stream.zalloc = Z_NULL;
stream.zfree = Z_NULL;
stream.opaque = Z_NULL;
if ((ret = do_inflate ? inflateInit(&stream) : deflateInit(&stream, 9)) != Z_OK) {
fclose(fp_in);
fclose(fp_out);
fprintf(stderr, "..flateInit error : %d\n", ret);
if(stream.msg != NULL) fprintf(stderr, "%s\n", stream.msg);
return 1;
}
inited = 1;
}
printf("input:%u\t", (unsigned int) stream.avail_in);
/* 出力バッファを指定する */
stream.next_out = output_buffer;
stream.avail_out = sizeof(output_buffer);
/* エンコード/デコードを実行する */
ret = (do_inflate ? inflate : deflate)(&stream, eof_detected ? Z_FINISH : Z_NO_FLUSH);
if (ret != Z_OK && ret != Z_STREAM_END) {
fprintf(stderr, "..flate error : %d\n", ret);
if(stream.msg != NULL) fprintf(stderr, "%s\n", stream.msg);
break;
}
printf("left_input:%u\t", (unsigned int) stream.avail_in);
printf("output:%u\n", (unsigned int) (sizeof(output_buffer) - stream.avail_out));
/* 出力があれば、書き出す */
if (stream.avail_out < sizeof(output_buffer)) {
fwrite(output_buffer, 1, sizeof(output_buffer) - stream.avail_out, fp_out);
}
/* 終端が検出されたら、処理を終了する */
if (ret == Z_STREAM_END) break;
}
/* ファイルクローズ */
fclose(fp_in);
fclose(fp_out);
/* 後始末 */
if ((ret = (do_inflate ? inflateEnd : deflateEnd)(&stream)) != Z_OK) {
fprintf(stderr, "..flateEnd error : %d\n", ret);
if(stream.msg != NULL) fprintf(stderr, "%s\n", stream.msg);
return 1;
}
return 0;
}
deflateの時はデータを貯められるだけ貯めてから吐き出す、
inflateの時はデータを生成したそばから吐き出す、ということがよくわかります。