Question

J'ai un fichier concaténé composé d'un certain nombre d'archives de bzip2. Je sais aussi la taille des morceaux individuels de bzip2 dans ce fichier.

Je voudrais décompresser un flux bzip2 à partir d'un bloc de données bzip2 individuelles et écrire la sortie standard.

Tout d'abord je utiliser fseek pour déplacer le curseur de fichier à l'octet archive désiré, puis lisez la -chunk « taille » du fichier dans un appel 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);

Le problème est que lorsque je compare la sortie de l'instruction fprintf avec sortie de l'exécution bzip2 sur la ligne de commande, je reçois deux réponses différentes.

Plus précisément, je reçois moins de sortie de ce code que de courir bzip2 sur la ligne de commande.

Plus précisément, ma sortie de ce code est un plus petit sous-ensemble de la sortie du processus de ligne de commande, et je manque ce qui est dans la fin de la queue du morceau bzip2 d'intérêt.

Je l'ai vérifié par une autre technique que la bzip2 commande en ligne fournit la bonne réponse, et, par conséquent, un problème avec mon code C provoque la sortie à la fin du morceau à disparaître. Je ne sais pas ce qu'est ce problème.

Si vous connaissez bzip2 ou libbzip2, pouvez-vous donner des conseils sur ce que je fais mal dans l'exemple de code ci-dessus? Je vous remercie de vos conseils.

Était-ce utile?

La solution

Ceci est mon code source:

#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;
}
  • Je pris en charge beaucoup sur la vérification des erreurs appropriée. Par exemple, je me suis assuré que bzError était BZ_OK ou BZ_STREAM_END avant d'essayer d'accéder à la mémoire tampon. La documentation indique clairement que pour d'autres valeurs de bzError le nombre de retour est non défini .
  • Il ne devrait pas vous faire peur que environ 50 pour cent du code sont concernés par la gestion des erreurs. Voilà comment il devrait être. Attendez-vous à des erreurs partout.
  • Le code a encore quelques bugs. En cas d'erreurs, il ne libère pas les ressources (f, bzf) correctement.

Et ce sont les commandes que j'utilisé pour le test:

$ 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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top