2009-11-30 12 views

Respuesta

5

Puede usar libzlib para abrir los archivos comprimidos gzip directamente.

También ofrece una función "gzopen" que se comporta de forma similar a fopen, pero opera en archivos gzip. Sin embargo, fscanf probablemente no funcionaría en dicho manipulador, ya que espera punteros FILE normales.

+0

Puede usar la función 'fdopen' para abrir una descripción de archivo como un puntero' FILE'. –

+1

Debe usar gzread en los archivos abiertos con gzopen - C no proporciona suficiente polimorfismo para que las bibliotecas definan descriptores de archivos "personalizados" o manejadores 'FILE *' que funcionen con POSIX o funciones de E/S estándar. Pero no creo que haya un gzscanf, así que tendrás que leer en un buffer y usar sscanf. –

0

Puede usar zlib, pero requerirá que reemplace sus llamadas de E/S para que sean específicas de zlib.

+0

También necesita el minizip libraray. La compresión en zip es la misma pero necesita el manejo del directorio virtual. –

0

tiene que abrir una tubería para hacer esto. El flujo básico en pseudo código es:

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 
} 

Puede utilizar las páginas man en los comentarios para más detalles sobre cómo hacer esto.

6

Si popen es un juego justo, puede hacerlo con fopen y 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; 
} 

Por ejemplo:

$ 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

Novato intento de 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

Puede usar zlib y envolverlo en un puntero de archivo normal, de esta manera puedes usar fscanf, fread, etc. transparentemente.

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

No utilice

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

para abrir archivos .gz. Correctamente escapar argv [1] en su lugar. De lo contrario, puede terminar con una vulnerabilidad, especialmente cuando algunos inyecta un argumento argv [1] como

123;rm -rf/

Ya ayuda a cambiar la instrucción anterior en

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

También puede escapar caracteres como '\ 0', '\' ',' \; ' etc.