3

いくつかのbzip2アーカイブで構成された連結ファイルがあります。bzip2また、そのファイル内の個々のチャンクのサイズも知っています。

bzip2個々の bzip2 データ チャンクからストリームを解凍し、出力を標準出力に書き込みたいと考えています。

まずfseek、ファイル カーソルを目的のアーカイブ バイトに移動してから、ファイルの「サイズ」チャンクをBZ2_bzRead呼び出しに読み込みます。

int headerSize = 1234;
int firstChunkSize = 123456;
FILE *fp = fopen("pathToConcatenatedFile", "r+b");
char *bzBuf = malloc(sizeof(char) * firstChunkSize);
int bzError, bzNBuf;
BZFILE *bzFp = BZ2_bzReadOpen(&bzError, *fp, 0, 0, NULL, 0);

# move cursor past header of known size, to the first bzip2 "chunk"
fseek(*fp, headerSize, SEEK_SET); 

while (bzError != BZ_STREAM_END) {
    # read the first chunk of known size, decompress it
    bzNBuf = BZ2_bzRead(&bzError, bzFp, bzBuf, firstChunkSize);
    fprintf(stdout, bzBuf);
}

BZ2_bzReadClose(&bzError, bzFp);
free(bzBuf);
fclose(fp);

fprintf問題は、ステートメントの出力とコマンド ラインで実行した出力を比較すると、bzip22 つの異なる答えが得られることです。

bzip2具体的には、このコードから得られる出力は、コマンド ラインで実行した場合よりも少なくなります。

より具体的には、このコードからの出力は、コマンド ライン プロセスからの出力の小さなサブセットであり、対象の bzip2 チャンクの末尾にあるものを見逃しています。

コマンドラインbzip2が正しい答えを提供していることを別の手法で確認しました。そのため、C コードの問題により、チャンクの最後の出力が失われています。その問題が何であるかはわかりません。

bzip2またはに精通している場合はlibbzip2、上記のコード サンプルで間違っている点について何かアドバイスをいただけますか? アドバイスありがとうございます。

4

1 に答える 1

5

これは私のソースコードです:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <bzlib.h>

int
bunzip_one(FILE *f) {
  int bzError;
  BZFILE *bzf;
  char buf[4096];

  bzf = BZ2_bzReadOpen(&bzError, f, 0, 0, NULL, 0);
  if (bzError != BZ_OK) {
    fprintf(stderr, "E: BZ2_bzReadOpen: %d\n", bzError);
    return -1;
  }

  while (bzError == BZ_OK) {
    int nread = BZ2_bzRead(&bzError, bzf, buf, sizeof buf);
    if (bzError == BZ_OK || bzError == BZ_STREAM_END) {
      size_t nwritten = fwrite(buf, 1, nread, stdout);
      if (nwritten != (size_t) nread) {
        fprintf(stderr, "E: short write\n");
        return -1;
      }
    }
  }

  if (bzError != BZ_STREAM_END) {
    fprintf(stderr, "E: bzip error after read: %d\n", bzError);
    return -1;
  }

  BZ2_bzReadClose(&bzError, bzf);
  return 0;
}

int
bunzip_many(const char *fname) {
  FILE *f;

  f = fopen(fname, "rb");
  if (f == NULL) {
    perror(fname);
    return -1;
  }

  fseek(f, 0, SEEK_SET);
  if (bunzip_one(f) == -1)
    return -1;

  fseek(f, 42, SEEK_SET); /* hello.bz2 is 42 bytes long in my case */
  if (bunzip_one(f) == -1)
    return -1;

  fclose(f);
  return 0;
}

int
main(int argc, char **argv) {
  if (argc < 2) {
    fprintf(stderr, "usage: bunz <fname>\n");
    return EXIT_FAILURE;
  }
  return bunzip_many(argv[1]) != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
  • 私は適切なエラーチェックに非常に気を配っていました。たとえば、バッファにアクセスしようとする前に、またはそれを確認しbzErrorました。ドキュメントには、返される数値の他の値はundefinedであることが明確に記載されています。BZ_OKBZ_STREAM_ENDbzError
  • コードの約 50% がエラー処理に関係していると言っても、驚くべきことではありません。そうあるべきです。どこでもエラーが予想されます。
  • コードにはまだいくつかのバグがあります。fエラーが発生した場合、リソース ( 、bzf) が適切に解放されません。

そして、これらは私がテストに使用したコマンドです:

$ echo hello > hello
$ echo world > world
$ bzip2 hello
$ bzip2 world
$ cat hello.bz2 world.bz2 > helloworld.bz2
$ gcc -W -Wall -Os -o bunz bunz.c -lbz2
$ ls -l *.bz2
-rw-r--r-- 1 roland None 42 Oct 12 09:26 hello.bz2
-rw-r--r-- 1 roland None 86 Oct 12 09:36 helloworld.bz2
-rw-r--r-- 1 roland None 44 Oct 12 09:26 world.bz2
$ ./bunz.exe helloworld.bz2 
hello
world
于 2010-10-12T07:42:05.633 に答える