みけCATのにっき(仮)
つれづれなるまゝに、日くらし、PCにむかひて、心に移りゆくよしなし事を、そこはかとなく書きつくれば、あやしうこそものぐるほしけれ。
(本当か!?)
出典

zlibを使ってみた

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

zlibを使ってみた

投稿記事 by みけCAT » 9年前

zlibを使ってみました。
これを使うと、データの圧縮・解凍が簡単にできます。

・導入方法
 何も考えずにダウンロード→解凍→configure→make→make installするだけの簡単なお仕事です。
 【訂正】何も考えずにconfigure→make→make installするだけの簡単なお仕事ではありません。
     make -f win32/Makefile.gccするだけの簡単なお仕事でした。
 または、コンパイラの配布サイトでもバイナリが配布されています。

・ドキュメント
 zlib 1.2.8 Manual

・ソースコード
基本の操作方法は至ってシンプル。
入力バッファがなくなったら足す。終わりなら終わりと言う。
出力バッファを投げて、データが出てきたら拾う。
それだけ。

CODE:

#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;
}
ついでに、入出力したデータの量をLTSVで書き出すようにしてみました。
deflateの時はデータを貯められるだけ貯めてから吐き出す、
inflateの時はデータを生成したそばから吐き出す、ということがよくわかります。
最後に編集したユーザー みけCAT on 2014年10月09日(木) 10:05 [ 編集 1 回目 ]
理由: zlibは素直にconfigure→make→make installするパターンじゃなかった

コメントはまだありません。