2009-11-30 115 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','\'','\;'等等。