Je tire des données d'un flux bzip2
dans une application C. Comme des morceaux de données sortent du décompresseur, ils peuvent être écrits stdout
:Comment gérer un flux de données interne à une application basée sur C?
fwrite(buffer, 1, length, stdout);
Cela fonctionne très bien. Je reçois toutes les données quand il est envoyé au stdout
.
au lieu d'écrire stdout
, je voudrais traiter la sortie de cette déclaration en interne dans une ligne-morceaux: une chaîne qui se termine par un retour à la ligne \n
. Est-ce que j'écris la sortie du flux de décompresseur dans un autre tampon, un caractère à la fois, jusqu'à ce que j'atteigne une nouvelle ligne, puis j'appelle la fonction de traitement par ligne? Est-ce lent et y a-t-il une approche plus intelligente? Merci pour vos conseils.
EDIT
Merci pour vos suggestions. J'ai fini par créer une paire de tampons qui stockent le reste (le "stub" à la fin d'un tampon de sortie) au début d'un tampon de ligne courte, chaque fois que je passe à travers la valeur de données du tampon de sortie.
Je boucle le caractère de sortie caractère par caractère et traite la valeur d'une ligne de nouvelle ligne à la fois. Le reste sans nouvelle ligne est alloué et affecté et copié dans le tampon de ligne du flux suivant. Il semble que realloc
est moins cher que les déclarations répétées malloc-free
.
Voici le code que je suis venu avec:
char bzBuf[BZBUFMAXLEN];
BZFILE *bzFp;
int bzError, bzNBuf;
char bzLineBuf[BZLINEBUFMAXLEN];
char *bzBufRemainder = NULL;
int bzBufPosition, bzLineBufPosition;
bzFp = BZ2_bzReadOpen(&bzError, *fp, 0, 0, NULL, 0); /* http://www.bzip.org/1.0.5/bzip2-manual-1.0.5.html#bzcompress-init */
if (bzError != BZ_OK) {
BZ2_bzReadClose(&bzError, bzFp);
fprintf(stderr, "\n\t[gchr2] - Error: Bzip2 data could not be retrieved\n\n");
return -1;
}
bzError = BZ_OK;
bzLineBufPosition = 0;
while (bzError == BZ_OK) {
bzNBuf = BZ2_bzRead(&bzError, bzFp, bzBuf, sizeof(bzBuf));
if (bzError == BZ_OK || bzError == BZ_STREAM_END) {
if (bzBufRemainder != NULL) {
/* fprintf(stderr, "copying bzBufRemainder to bzLineBuf...\n"); */
strncpy(bzLineBuf, bzBufRemainder, strlen(bzBufRemainder)); /* leave out \0 */
bzLineBufPosition = strlen(bzBufRemainder);
}
for (bzBufPosition = 0; bzBufPosition < bzNBuf; bzBufPosition++) {
bzLineBuf[bzLineBufPosition++] = bzBuf[bzBufPosition];
if (bzBuf[bzBufPosition] == '\n') {
bzLineBuf[bzLineBufPosition] = '\0'; /* terminate bzLineBuf */
/* process the line buffer, e.g. print it out or transform it, etc. */
fprintf(stdout, "%s", bzLineBuf);
bzLineBufPosition = 0; /* reset line buffer position */
}
else if (bzBufPosition == (bzNBuf - 1)) {
bzLineBuf[bzLineBufPosition] = '\0';
if (bzBufRemainder != NULL)
bzBufRemainder = (char *)realloc(bzBufRemainder, bzLineBufPosition);
else
bzBufRemainder = (char *)malloc(bzLineBufPosition);
strncpy(bzBufRemainder, bzLineBuf, bzLineBufPosition);
}
}
}
}
if (bzError != BZ_STREAM_END) {
BZ2_bzReadClose(&bzError, bzFp);
fprintf(stderr, "\n\t[gchr2] - Error: Bzip2 data could not be uncompressed\n\n");
return -1;
} else {
BZ2_bzReadGetUnused(&bzError, bzFp, 0, 0);
BZ2_bzReadClose(&bzError, bzFp);
}
free(bzBufRemainder);
bzBufRemainder = NULL;
J'apprécie vraiment l'aide de tout le monde. Cela fonctionne bien.
strtok pourrait vous éviter de vérifier le retour à la ligne sur chaque caractère dans le tampon. – Tumas
'strtok' est ce que j'ai essayé précédemment, mais cela ne fonctionne pas pour moi et je perds des données, car le tampon de sortie sortant du décompresseur bzip2 est divisé sur une ligne. Je perds ce peu à la fin. Peut-être que je l'utilise incorrectement. Y a-t-il une utilisation de 'strtok' qui permet de garder le" stub "sans nouvelle ligne, en collant ce bout au début du morceau de tampon de sortie suivant? –
Non, vous avez raison, strtok ne correspond pas tout à fait ici. Vous perdez ce bit si vous utilisez strtok et il est probablement plus facile de vérifier chaque caractère. Je ne connais aucun moyen astucieux d'enregistrer ce "stub" sans nouvelle ligne pour une utilisation ultérieure, sauf pour le faire manuellement, comme l'a décrit Opera. Désolé, pour vous tromper un peu :) – Tumas