2009-11-30 33 views

回答

5

您可以使用libzlib直接打开gzip文件。

它还提供了一个“gzopen”功能,其功能类似于fopen,但对gzip文件进行操作。但是,fscanf可能无法在这样的句柄上工作,因为它期望正常的FILE指针。

+0

您可以使用'fdopen'函数打开一个文件描述符作为'FILE'指针。 – 2009-11-30 14:32:08

+1

您必须对使用gzopen打开的文件使用gzread - C没有为库提供足够的多态性来定义可用于POSIX或标准I/O函数的“自定义”文件描述符或“FILE *”句柄。但我不认为有一个gzscanf,所以你必须读入一个缓冲区并使用sscanf。 – 2009-11-30 16:12:20

0

您可以使用zlib,但它会要求您将您的I/O调用替换为zlib特定的。

+0

你还需要minizip libraray。 zip中的压缩是相同的,但您需要虚拟目录处理。 – 2009-11-30 16:01:18

0

你必须打开一个管道才能做到这一点。在伪代码的基本流程是:

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 
} 

您可以使用注释的man页有关如何做到这一点的更多细节。

6

如果popen是公平的游戏,你可以用fopenfscanf做到这一点:

#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; 
} 

例如:

$ 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

在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

这种方式可以使用zlib并将其包装为常规文件指针你可以使用fscanf,fread等。透明。

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

不要使用

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

打开。广州文件。改为正确地转义argv [1]。否则可能会最终有一个漏洞,尤其是当一些注入的argv [1]如

123;rm -rf/

它已经有助于改变上述指令到

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

你也可以想逃避争论字符如'\ 0','\'','\;'等等。