An example of compressing with zlib in C

This is an example C program illustrating compressing data using zlib. The program compresses a short piece of text in message variable and prints the compressed message to stdout. This will result in a strange message if printed to a terminal.

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

(download)

The output of the example, passed through hexdump -C, looks like this:

00000000  1f 8b 08 00 00 00 00 00  00 03 3d 8e 31 0e c2 30  |..........=.1..0|
00000010  0c 45 f7 9c e2 6f 2c 9c  00 06 c4 c8 c0 02 5c c0  |.E...o,.......\.|
00000020  10 53 57 24 75 95 38 45  b9 3d 2e 48 2c 96 2c ff  |.SW$u.8E.=.H,.,.|
00000030  f7 be af 42 29 e1 84 87  e6 99 0a c3 84 7d 28 08  |...B)........}(.|
00000040  b5 e5 cc 65 53 11 a9 1f  c2 4d b4 81 8a 21 ab a7  |...eS....M...!..|
00000050  92 2e 9c 3a 68 8a bf dd  38 cf 5c c8 78 17 2e da  |...:h...8.\.x...|
00000060  06 c1 7b 9c a2 93 8a 2a  f4 fa 5a 5d 53 d2 38 0d  |..{....*..Z]S.8.|
00000070  b8 37 bf e8 13 67 ea db  70 74 c3 bf 28 31 55 86  |.7...g..pt..(1U.|
00000080  90 09 d6 a7 4c 57 5c bd  93 1c 36 de 87 0f 75 d8  |....LW\...6...u.|
00000090  63 17 ad 00 00 00                                 |c.....|
00000096

In order to reconstruct the original text, pass it through gzcat like this:

./a.out | gzcat

This will print the text contained in message on to the terminal, and confirm that the compression has worked correctly.


Copyright © Ben Bullock 2009-2017. All rights reserved. For comments, questions, and corrections, please email Ben Bullock (benkasminbullock@gmail.com). / Privacy / Disclaimer