pbzip2で圧縮したファイルを伸張する
以前作成したプログラム(bzip2で圧縮したファイルの伸張はできる)で、pbzpi2(Parallel BZIP2)で圧縮したファイルの伸張が行えなかったので対応させた。
そのときのテストプログラム。
bz2test.cpp
#include <stdio.h>
#include <stdlib.h>
#include <bzlib.h>
int main(int argc, char const* argv[])
{
FILE *fp = fopen(argv[1], "rb");
if (fp == NULL) return 1;
int bzerror;
char unused[BZ_MAX_UNUSED];
int unusedLen = 0;
BZFILE* bz2in = BZ2_bzReadOpen(&bzerror, fp, 0, 0, unused, unusedLen);
if (bzerror != BZ_OK) return 2;
bzerror = BZ_OK;
int length = 512;
void* buffer = malloc(length);
while (true) {
if (bzerror == BZ_STREAM_END && feof(fp)) {
break;
}
uint n = BZ2_bzRead(&bzerror, bz2in, buffer, length);
if (bzerror != BZ_OK && bzerror != BZ_STREAM_END) {
return 3;
}
if (bzerror == BZ_STREAM_END && !feof(fp)) {
void* unusedTemp = NULL;
BZ2_bzReadGetUnused(&bzerror, bz2in, &unusedTemp, &unusedLen);
if (bzerror != BZ_OK) {
return 4;
}
for (int i=0; i<unusedLen; i++) {
unused[i] = ((char*)unusedTemp)[i];
}
BZ2_bzReadClose(&bzerror, bz2in);
if (bzerror != BZ_OK) {
return 5;
}
bz2in = BZ2_bzReadOpen(&bzerror, fp, 0, 0, unused, unusedLen);
if (bzerror != BZ_OK) {
return 6;
}
uint n2 = BZ2_bzRead(&bzerror, bz2in, (char*)buffer + n, length - n);
if (bzerror == BZ_DATA_ERROR_MAGIC || bzerror == BZ_DATA_ERROR) {
return 7;
}
if (bzerror != BZ_OK) {
return 8;
}
}
}
free(buffer);
return 0;
}
環境
CentOS6.5
bzip2 Version 1.0.5
Parallel BZIP2 v1.1.6
コンパイル
g++ bz2test.cpp -lbz2
bzip2とpbzip2の違い
bzip2はシングルストリームであるがpbzip2はマルチストリーム。
こんなイメージ。
bzip2
[----------------------bzip2----------------------]
pbzip2
[--bzip2--|--bzip2--|--bzip2--|--bzip2--|--bzip2--]
pbzip2はbzip2で圧縮したデータが連続して格納されているため、bzip2として伸張しても途中までしか伸張したことにならない。
ストリームが終了(BZ_STREAM_END)したら、再度オープンして次のストリーム(1つのbzip2圧縮データ)を伸張する必要がある。
そのときに直前のストリームで伸張しきれていないデータを保持(BZ2_bzReadGetUnused)しておく。