Skip to content

Instantly share code, notes, and snippets.

@arq5x
Last active November 30, 2023 12:50
Show Gist options
  • Star 63 You must be signed in to star a gist
  • Fork 15 You must be signed in to fork a gist
  • Save arq5x/5315739 to your computer and use it in GitHub Desktop.
Save arq5x/5315739 to your computer and use it in GitHub Desktop.
Compress and then Decompress a string with zlib.
# compile
$ g++ zlib-example.cpp -lz -o zlib-example
# run
$ ./zlib-example
Uncompressed size is: 36
Uncompressed string is: Hello Hello Hello Hello Hello Hello!
----------
Compressed size is: 13
Compressed string is: x��H���W��G*2
----------
Uncompressed size is: 36
Uncompressed string is: Hello Hello Hello Hello Hello Hello!
#include <stdio.h>
#include <string.h> // for strlen
#include <assert.h>
#include "zlib.h"
// adapted from: http://stackoverflow.com/questions/7540259/deflate-and-inflate-zlib-h-in-c
int main(int argc, char* argv[])
{
// original string len = 36
char a[50] = "Hello Hello Hello Hello Hello Hello!";
// placeholder for the compressed (deflated) version of "a"
char b[50];
// placeholder for the UNcompressed (inflated) version of "b"
char c[50];
printf("Uncompressed size is: %lu\n", strlen(a));
printf("Uncompressed string is: %s\n", a);
printf("\n----------\n\n");
// STEP 1.
// deflate a into b. (that is, compress a into b)
// zlib struct
z_stream defstream;
defstream.zalloc = Z_NULL;
defstream.zfree = Z_NULL;
defstream.opaque = Z_NULL;
// setup "a" as the input and "b" as the compressed output
defstream.avail_in = (uInt)strlen(a)+1; // size of input, string + terminator
defstream.next_in = (Bytef *)a; // input char array
defstream.avail_out = (uInt)sizeof(b); // size of output
defstream.next_out = (Bytef *)b; // output char array
// the actual compression work.
deflateInit(&defstream, Z_BEST_COMPRESSION);
deflate(&defstream, Z_FINISH);
deflateEnd(&defstream);
// This is one way of getting the size of the output
printf("Compressed size is: %lu\n", strlen(b));
printf("Compressed string is: %s\n", b);
printf("\n----------\n\n");
// STEP 2.
// inflate b into c
// zlib struct
z_stream infstream;
infstream.zalloc = Z_NULL;
infstream.zfree = Z_NULL;
infstream.opaque = Z_NULL;
// setup "b" as the input and "c" as the compressed output
infstream.avail_in = (uInt)((char*)defstream.next_out - b); // size of input
infstream.next_in = (Bytef *)b; // input char array
infstream.avail_out = (uInt)sizeof(c); // size of output
infstream.next_out = (Bytef *)c; // output char array
// the actual DE-compression work.
inflateInit(&infstream);
inflate(&infstream, Z_NO_FLUSH);
inflateEnd(&infstream);
printf("Uncompressed size is: %lu\n", strlen(c));
printf("Uncompressed string is: %s\n", c);
// make sure uncompressed is exactly equal to original.
assert(strcmp(a,c)==0);
return 0;
}
@Barium
Copy link

Barium commented May 25, 2014

Is strlen really the right way to find size of compressed data? Can't the compressed data contain null-bytes? (line: 45)

@hitxiang
Copy link

strlen should be replaced by infstream.total_out
printf("Uncompressed size is: %lu\n", infstream.total_out);
printf("Uncompressed string is: %.*s\n", infstream.total_out, c);

@YF-Tung
Copy link

YF-Tung commented Aug 22, 2016

Thanks a lot for the comment of @hitxiang, it's really helpful.
line 45 should be
printf("Compressed size is: %lu\n", defstream.total_out);

@gustavo4passos
Copy link

I was looking for a quick example and found this.
Very helpful, thanks!

@ankitpateledu
Copy link

I have modified your code to use random string by merging another example i found for random string generation; i found that with random string generated the compression doesn't work; meaning compressed and uncompressed length are same ; furthermore compressing compressed string always results in 3 less chars from tail . with default "hello" string as in original example it does compress and results are identical as you have shown.

do you see any reason, why this code should fail for random strings?

#include <stdio.h> 
#include <string.h>  // for strlen
#include <assert.h>
#include "zlib.h"
//#include <random.h>
#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
// adapted from: http://stackoverflow.com/questions/7540259/deflate-and-inflate-zlib-h-in-c

static const char alphanum[] =
"0123456789"
"!@#$%^&*"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";

int stringLength = sizeof(alphanum) - 1;

int length = 50;

int main(int argc, char* argv[])
{
    // original string len = 36
    //char a[50] = "Hello Hello Hello Hello Hello Hello!";
    char a[length];
    // placeholder for the compressed (deflated) version of "a" 
    char b[length];

    // placeholder for the UNcompressed (inflated) version of "b"
    char c[length];


    srand(time(0));
//std::string a;
    for(unsigned int j = 0; j < 1; ++j)
    {
        //a = "";
        for(unsigned int i = 0; i < length ; ++i)
        {
        a[i]= alphanum[rand() % stringLength];

        }
                //char a[50]="Hello Hello Hello Hello Hello Hello!";
                printf("Uncompressed size is: %lu\n", strlen(a));
                printf("Uncompressed string is: %s\n", a);


                printf("\n----------\n\n");

                // STEP 1.
                // deflate a into b. (that is, compress a into b)

                // zlib struct
                z_stream defstream;
                defstream.zalloc = Z_NULL;
                defstream.zfree = Z_NULL;
                defstream.opaque = Z_NULL;
                // setup "a" as the input and "b" as the compressed output
                defstream.avail_in = (uInt)strlen(a)+1; // size of input, string + terminator
                defstream.next_in = (Bytef *)a; // input char array
                defstream.avail_out = (uInt)sizeof(b); // size of output
                defstream.next_out = (Bytef *)b; // output char array

                // the actual compression work.
                deflateInit(&defstream, Z_BEST_COMPRESSION);
                deflate(&defstream, Z_FINISH);
                deflateEnd(&defstream);
  // This is one way of getting the size of the output
                printf("Compressed size is: %lu\n", strlen(b));
                printf("Compressed string is: %s\n", b);


                printf("\n----------\n\n");
		// STEP 2.
    // inflate b into c
    // zlib struct
    z_stream infstream;
    infstream.zalloc = Z_NULL;
    infstream.zfree = Z_NULL;
    infstream.opaque = Z_NULL;
    // setup "b" as the input and "c" as the compressed output
    infstream.avail_in = (uInt)((char*)defstream.next_out - b); // size of input
    infstream.next_in = (Bytef *)b; // input char array
    infstream.avail_out = (uInt)sizeof(c); // size of output
    infstream.next_out = (Bytef *)c; // output char array
     
    // the actual DE-compression work.
    inflateInit(&infstream);
    inflate(&infstream, Z_NO_FLUSH);
    inflateEnd(&infstream);
     
    printf("Uncompressed size is: %lu\n", strlen(c));
    printf("Uncompressed string is: %s\n", c);
    

    // make sure uncompressed is exactly equal to original.
               
        }
        return 0;
}

and results are

 ./c.out 
Uncompressed size is: 50
Uncompressed string is: i5dY0LNq4^yilrkQqJYuW037$u^CDcw^hlzu^NwNou%Zx!8zfg

----------

Compressed size is: 50
706W)�svI.���*���/U��P��4M�4�+4���)�,�

----------

Uncompressed size is: 47
Uncompressed string is: i5dY0LNq4^yilrkQqJYuW037$u^CDcw^hlzu^NwNou%Zx!8

@pnhathung
Copy link

Your length of array should be 51.

@jasonchristopherchandra

does this run on windows ?

@shaheerakr
Copy link

when i am running this code this in giving me this error
error C2275: 'z_stream' : illegal use of this type as an expression

@denisdemaisbr
Copy link

be ware using strlen() with binary data

// defstream.avail_in = (uInt)strlen(a)+1;

@daarisameen
Copy link

How to execute these programs in windows

@daarisameen
Copy link

does this run on windows ?

no ig

@stefanasandei
Copy link

stefanasandei commented Aug 3, 2021

How to execute these programs in windows

install windows subsystem for linux and run the code from the linux environment

@HarikrishnaR-OPTM
Copy link

Input File: file size: 52946 Aug 23 17:23 RGB_16bits_palette_sample_image.png
Output Comp File: file size: 52972 Aug 23 17:35 zlib_comp_16bits.j2k
Output DeComp File: file size: 52946 Aug 23 17:35 zlib_decomp_16bits.png

Why the output Compressed file size becoming greater then the ( 52972 > 52946) Input file size ?

@denisdemaisbr
Copy link

It's normal.
recompressing data almost always increases the size.

@SirObby
Copy link

SirObby commented Nov 17, 2021

Is this possible without the array length? like instead of [90] we could have []?

@halloweeks
Copy link

Yes. without array length
use const char* myvar;

@anasouardini-old
Copy link

anasouardini-old commented Apr 30, 2022

How do I use this dynamically without knowing the output size, (when decompressing)

@mcfriend99
Copy link

@anasouardini Did you find any answer?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment