Domanda

Ho un file concatenati composto da alcuni numero di archivi bzip2. So anche le dimensioni dei singoli pezzi bzip2 in quel file.

Vorrei decomprimere un flusso bzip2 da un individuo blocco di dati bzip2, e scrivere l'output sullo standard output.

Per prima cosa l'uso fseek per spostare il cursore di file al byte archivio desiderato, e poi leggere il -chunk "dimensioni" del file in una chiamata 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);

Il problema è che quando ho confrontare l'uscita della dichiarazione fprintf con uscita esecuzione bzip2 sulla riga di comando, ottengo due risposte diverse.

In particolare, ottengo meno uscita da questo codice di esecuzione bzip2 sulla riga di comando.

In particolare, la mia uscita da questo codice è un sottoinsieme più piccolo dell'uscita dal processo riga di comando, e mi manca ciò che è nella coda-fine dello spezzone bzip2 di interesse.

Ho verificato attraverso un'altra tecnica che la linea di comando bzip2 fornisce la risposta corretta, e, pertanto, qualche problema con il mio codice C provoca uscita alla fine dello spezzone di andare dispersi. Io non so che cosa quel problema è.

Se si ha familiarità con bzip2 o libbzip2, Potete fornire qualche consiglio su quello che sto facendo di sbagliato nel codice di esempio di cui sopra? Grazie per i vostri consigli.

È stato utile?

Soluzione

Questo è il mio codice sorgente:

#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;
}
  • I importava molto di adeguata verifica degli errori. Per esempio, ho fatto in modo che fosse bzError BZ_OK o BZ_STREAM_END prima di tentare di accedere al buffer. La documentazione dice chiaramente che per altri valori di bzError il numero restituito è non definita .
  • Dovrebbe Non ti spaventi che circa il 50 per cento del codice si occupano di gestione degli errori. Ecco come dovrebbe essere. Aspettatevi errori ovunque.
  • Il codice ha ancora alcuni bug. In caso di errori che non rilascia le risorse (f, bzf) correttamente.

E questi sono i comandi che ho usato per il 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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top