2009-11-30 15 views

risposta

5

È possibile utilizzare libzlib per aprire direttamente i file compressi con gzip.

offre anche una funzione di "gzopen" che si comporta simile a fopen, ma opera su file compressi con gzip. Tuttavia, fscanf probabilmente non funzionerebbe su un simile handle, dal momento che prevede puntatori FILE normali.

+0

È possibile utilizzare la funzione 'fdopen' per aprire un descrittto di file come un puntatore' FILE'. –

+1

È necessario utilizzare gzread sui file aperti con gzopen - C non fornisce sufficiente polimorfismo per le librerie per definire descrittori di file "personalizzati" o handle "FILE *" che funzionano con POSIX o funzioni di I/O standard. Ma non penso che ci sia un gzscanf, quindi dovrai leggere in un buffer e usare sscanf. –

0

È possibile utilizzare zlib, ma richiederà di sostituire il vostro I/O chiama ad essere specifici per zlib.

+0

È inoltre necessario il Libraray Minizip. La compressione in zip è la stessa, ma è necessaria la gestione della directory virtuale. –

0

è necessario aprire un tubo per fare questo. Il flusso di base in pseudo-codice è:

create pipe // man pipe 

fork // man fork 

if (parent) { 
    close the writing end of the pipe // man 2 close 
    read from the pipe // man 2 read 
} else if (child) { 
    close the reading end of the pipe // man 2 close 
    overwrite the file descriptor for stdout with the writing end of the pipe // man dup2 
    call exec() with gzip and the relevant parameters // man 3 exec 
} 

Offriamo le man pagine nei commenti per maggiori dettagli su come fare questo.

6

Se popen è giusto gioco, è possibile farlo con fopen e fscanf:

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

int main(int argc, char *argv[]) 
{ 
    const char prefix[] = "zcat "; 
    const char *arg; 
    char *cmd; 
    FILE *in; 
    char buf[4096]; 

    if (argc != 2) { 
    fprintf(stderr, "Usage: %s file\n", argv[0]); 
    return 1; 
    } 

    arg = argv[1]; 
    cmd = malloc(sizeof(prefix) + strlen(arg) + 1); 
    if (!cmd) { 
    fprintf(stderr, "%s: malloc: %s\n", argv[0], strerror(errno)); 
    return 1; 
    } 

    sprintf(cmd, "%s%s", prefix, arg); 

    in = popen(cmd, "r"); 
    if (!in) { 
    fprintf(stderr, "%s: popen: %s\n", argv[0], strerror(errno)); 
    return 1; 
    } 

    while (fscanf(in, "%s", buf) == 1) 
    printf("%s: got [%s]\n", argv[0], buf); 

    if (ferror(in)) { 
    fprintf(stderr, "%s: fread: %s\n", argv[0], strerror(errno)); 
    return 1; 
    } 
    else if (!feof(in)) { 
    fprintf(stderr, "%s: %s: unconsumed input\n", argv[0], argv[1]); 
    return 1; 
    } 

    return 0; 
} 

Ad esempio:

$ zcat file.gz 
Every good boy does fine. 
$ ./gzread file.gz 
./gzread: got [Every] 
./gzread: got [good] 
./gzread: got [boy] 
./gzread: got [does] 
./gzread: got [fine.] 
1

Newbie tentativo di gzscanf():

#include <stdio.h> 
#include <stdarg.h> 
#include <zlib.h> 

#define MAXLEN 256 

int gzscanf(gzFile *stream, const char *fmt, ...) { 
    /* read one line from stream (up to newline) and parse with sscanf */ 
    va_list args; 
    va_start(args, fmt); 
    int n; 
    static char buf[MAXLEN]; 

    if (NULL == gzgets(stream, buf, MAXLEN)) { 
    printf("gzscanf: Failed to read line from gz file.\n"); 
    exit(EXIT_FAILURE); 
    } 
    n = vsscanf(buf, fmt, args); 
    va_end(args); 
    return n; 
} 
0

Puoi usare zlib e avvolgerlo in un normale puntatore di file, in questo modo puoi usare fscanf, fread, ecc. in modo trasparente.

FILE *myfopen(const char *path, const char *mode) 
{ 
#ifdef WITH_ZLIB 
    gzFile *zfp; 

    /* try gzopen */ 
    zfp = gzopen(path,mode); 
    if (zfp == NULL) 
    return fopen(path,mode); 

    /* open file pointer */ 
    return funopen(zfp, 
       (int(*)(void*,char*,int))gzread, 
       (int(*)(void*,const char*,int))gzwrite, 
       (fpos_t(*)(void*,fpos_t,int))gzseek, 
       (int(*)(void*))gzclose); 
#else 
    return fopen(path,mode); 
#endif 
} 
3

Non utilizzare

sprintf(cmd, "zcat %s", argv[1]); 
popen(cmd,"r"); 

per aprire i file .gz. Risolvi correttamente argv [1]. Si può altrimenti finire con una vulnerabilità, soprattutto quando alcuni inietta un argomento argv [1] come

123;rm -rf/

Contribuisce già a cambiare le istruzioni sopra in

sprintf(cmd, "zcat \'%s\'",argv[1]); 

Si consiglia inoltre di fuggire caratteri come '\ 0', '\' ',' \; ' ecc.