Frage

Ich habe eine verkettete Datei von einer Anzahl von bzip2 Archiven aus. Ich weiß, dass auch die Größen der einzelnen bzip2 Stücke in dieser Datei.

Ich möchte einen bzip2 Strom von einem einzelnen bzip2 Datenblock dekomprimieren, und die Ausgabe auf die Standardausgabe schreiben.

Zuerst habe ich Gebrauch fseek die Datei Cursor auf das gewünschte Archiv Byte zu bewegen, und dann lesen Sie die „Größe“ -chunk der Datei in einen BZ2_bzRead Aufruf:

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);

Das Problem ist, dass, wenn ich die Ausgabe der fprintf Anweisung mit Ausgang vergleichen von laufenden bzip2 auf der Kommandozeile, bekomme ich zwei verschiedene Antworten.

Insbesondere bekomme ich weniger Ausgabe von diesem Code als von bzip2 auf der Kommandozeile ausgeführt wird.

Insbesondere aus diesem Code meine Ausgabe ist eine kleinere Teilmenge des Ausgangs von der Kommandozeile Prozess, und ich bin fehle, was in dem Schwanzende des bzip2 Brockens von Interesse.

Ich habe durch eine andere Technik Nachweis erbracht, dass die Befehlszeile bzip2 die richtige Antwort liefert, und daher ein Problem mit meinem C-Code ausgegeben wird am Ende des Blockes verursacht abhanden zu kommen. Ich weiß nur nicht, was das Problem ist.

Wenn Sie mit bzip2 oder libbzip2 vertraut sind, können Sie bieten einen Rat, was ich oben falsch in dem Codebeispiel mache? Vielen Dank für Ihre Beratung.

War es hilfreich?

Lösung

Das ist mein Quellcode:

#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;
}
  • Ich sorgte mich sehr viel über die richtige Fehlerprüfung. Zum Beispiel habe ich darauf geachtet, dass bzError war BZ_OK oder BZ_STREAM_END, bevor Sie den Puffer zugreifen. Die Dokumentation sagt deutlich, dass für andere Werte von bzError die zurückgegebene Zahl ist undefined .
  • Es sollte Sie nicht erschrecken, dass etwa 50 Prozent des Codes mit Fehlerbehandlung betroffen sind. Das ist wie es sein sollte. Erwarten Sie Fehler überall.
  • Der Code hat noch einige Bugs. Bei Fehlern entbindet sie nicht über die Ressourcen (f, bzf) richtig.

Und das sind die Befehle, die ich für den Test verwendet:

$ 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
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top