zlib压缩、解压缩gzip文件

默认zlib的API,是只压缩数据,无法处理gzip文件的,因为无法解析头文件信息。

备注:初始化参数那个,也可以这么搞 MAX_WBITS + 16,读了Python的源码用的是这种方法。

以下转载自:http://www.lemoda.net/c/zlib-open-read/

压缩:

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

/* CHUNK is the size of the memory chunk used by the zlib routines. */

#define CHUNK 0x4000

/* The following macro calls a zlib routine and checks the return
   value. If the return value ("status") is not OK, it prints an error
   message and exits the program. Zlib's error statuses are all less
   than zero. */

#define CALL_ZLIB(x) {                                                  \
        int status;                                                     \
        status = x;                                                     \
        if (status < 0) {                                               \
            fprintf (stderr,                                            \
                     "%s:%d: %s returned a bad status of %d.\n",        \
                     __FILE__, __LINE__, #x, status);                   \
            exit (EXIT_FAILURE);                                        \
        }                                                               \
    }

/* These are parameters to deflateInit2. See
   http://zlib.net/manual.html for the exact meanings. */

#define windowBits 15
#define GZIP_ENCODING 16

static void strm_init (z_stream * strm)
{
    strm->zalloc = Z_NULL;
    strm->zfree  = Z_NULL;
    strm->opaque = Z_NULL;
    CALL_ZLIB (deflateInit2 (strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
                             windowBits | GZIP_ENCODING, 8,
                             Z_DEFAULT_STRATEGY));
}

/* Example text to print out. */

static const char * message = 
"Shall I compare thee to a summer's day?\n"
"Thou art more lovely and more temperate:\n"
"Rough winds do shake the darling buds of May,\n"
"And summer's lease hath all too short a date;\n"
;

int main ()
{
    unsigned char out[CHUNK];
    z_stream strm;
    strm_init (& strm);
    strm.next_in = (unsigned char *) message;
    strm.avail_in = strlen (message);
    do {
        int have;
        strm.avail_out = CHUNK;
        strm.next_out = out;
        CALL_ZLIB (deflate (& strm, Z_FINISH));
        have = CHUNK - strm.avail_out;
        fwrite (out, sizeof (char), have, stdout);
    }
    while (strm.avail_out == 0);
    deflateEnd (& strm);

    return 0;
}

 

解压缩:

#include <stdio.h>
/* For "exit". */
#include <stdlib.h>
/* For "strerror". */
#include <string.h>
/* For "errno". */
#include <errno.h>
#include <zlib.h>

/* CHUNK is the size of the memory chunk used by the zlib routines. */

#define CHUNK 0x4000

/* The following macro calls a zlib routine and checks the return
   value. If the return value ("status") is not OK, it prints an error
   message and exits the program. Zlib's error statuses are all less
   than zero. */

#define CALL_ZLIB(x) {                                                  \
        int status;                                                     \
        status = x;                                                     \
        if (status < 0) {                                               \
            fprintf (stderr,                                            \
                     "%s:%d: %s returned a bad status of %d.\n",        \
                     __FILE__, __LINE__, #x, status);                   \
            exit (EXIT_FAILURE);                                        \
        }                                                               \
    }

/* if "test" is true, print an error message and halt execution. */

#define FAIL(test,message) {                             \
        if (test) {                                      \
            inflateEnd (& strm);                         \
            fprintf (stderr, "%s:%d: " message           \
                     " file '%s' failed: %s\n",          \
                     __FILE__, __LINE__, file_name,      \
                     strerror (errno));                  \
            exit (EXIT_FAILURE);                         \
        }                                                \
    }

/* These are parameters to inflateInit2. See
   http://zlib.net/manual.html for the exact meanings. */

#define windowBits 15
#define ENABLE_ZLIB_GZIP 32

int main ()
{
    const char * file_name = "test.gz";
    FILE * file;
    z_stream strm = {0};
    unsigned char in[CHUNK];
    unsigned char out[CHUNK];

    strm.zalloc = Z_NULL;
    strm.zfree = Z_NULL;
    strm.opaque = Z_NULL;
    strm.next_in = in;
    strm.avail_in = 0;
    CALL_ZLIB (inflateInit2 (& strm, windowBits | ENABLE_ZLIB_GZIP));

    /* Open the file. */

    file = fopen (file_name, "rb");
    FAIL (! file, "open");
    while (1) {
        int bytes_read;

        bytes_read = fread (in, sizeof (char), sizeof (in), file);
        FAIL (ferror (file), "read");
        strm.avail_in = bytes_read;
        do {
	    unsigned have;
            strm.avail_out = CHUNK;
	    strm.next_out = out;
            CALL_ZLIB (inflate (& strm, Z_NO_FLUSH));
	    have = CHUNK - strm.avail_out;
	    fwrite (out, sizeof (unsigned char), have, stdout);
        }
        while (strm.avail_out == 0);
        if (feof (file)) {
            inflateEnd (& strm);
            break;
        }
    }
    FAIL (fclose (file), "close");
    return 0;
}

 

Leave a Reply

Your email address will not be published.