2009-11-30 10 views
7

मेरे पास कुछ gzipped फ़ाइलें हैं जिन्हें मैं fopen और fscanf के माध्यम से सी में पढ़ना चाहता हूं। फाइलों को अस्थायी फ़ाइलों में बंद करने के बिना ऐसा करने के लिए वैसे भी है?अस्थायी फ़ाइलों को बनाने के बिना सी में पढ़ने के लिए gzipped फ़ाइलों को खोलना

धन्यवाद।

उत्तर

5

आप gzipped फ़ाइलों को सीधे खोलने के लिए libzlib का उपयोग कर सकते हैं।

यह एक "gzopen" फ़ंक्शन भी प्रदान करता है जो फॉपेन के समान व्यवहार करता है लेकिन gzipped फ़ाइलों पर काम करता है। हालांकि, fscanf शायद इस तरह के हैंडल पर काम नहीं करेगा, क्योंकि यह सामान्य फ़ाइल पॉइंटर्स की अपेक्षा करता है।

+0

आप 'फ़ाइल' सूचक के रूप में फ़ाइल फ़ाइल को खोलने के लिए 'fdopen' फ़ंक्शन का उपयोग कर सकते हैं। –

+1

आपको gzopen के साथ खोले गए फ़ाइलों पर gzread का उपयोग करना है - सी पुस्तकालयों के लिए "कस्टम" फ़ाइल डिस्क्रिप्टर या 'FILE *' हैंडल को परिभाषित करने के लिए पर्याप्त पॉलीमोर्फिज्म प्रदान नहीं करता है जो POSIX या मानक I/O फ़ंक्शंस के साथ काम करता है। लेकिन मुझे नहीं लगता कि एक gzscanf है, इसलिए आपको एक बफर में पढ़ना होगा और sscanf का उपयोग करना होगा। –

0

आप zlib का उपयोग कर सकते हैं, लेकिन इसके लिए आपको अपनी आई/ओ कॉल को ज़्लिब-विशिष्ट होने की आवश्यकता होगी।

+0

आपको मिनीजिप लाइब्रारे की भी आवश्यकता है। ज़िप में संपीड़न समान है लेकिन आपको वर्चुअल निर्देशिका हैंडलिंग की आवश्यकता है। –

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 निष्पक्ष खेल है, तो आप fopen और 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; 
} 

उदाहरण के लिए:

$ 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"); 

फ़ाइलों .gz खोलने के लिए उपयोग न करें। इसके बजाय argv [1] उचित रूप से बचें। आप अन्यथा एक जोखिम के साथ खत्म हो सकता है, खासकर जब कुछ argv [1] इस तरह के

123;rm -rf/

के रूप में यह पहले से ही

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

में ऊपर दिए गए निर्देश बदलने में मदद करता आप भी बचने के लिए चाहते हो सकता है एक तर्क injects '\ 0', '\' ',' \; 'जैसे वर्ण आदि

संबंधित मुद्दे