1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

libbz2を使ってpbzip2で圧縮したファイルを伸張する

Posted at

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)しておく。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?