# Compress File with zlib

This topic is 5408 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I have been unable to exactly decipher what the zlib functions are do, as they simply dont seem straight forward to me,id be fine if i could find a code example somewhere, but a c tutoiral of zlib is extremly hard to come across apparently. If somone would please just show me how to read an uncompressed file, compress it, and store it in another file, i would be greatly appreciative. thank you.

##### Share on other sites
Take a look at compress.c in the root of the ZLIB source. That demonstrates the simple case of compressing data in a buffer into another buffer.

You shouldn't need much more unless you want to start using the streaming features - but I'd still reccommed starting with compressing a whole buffer in memory.

##### Share on other sites
the zlib manual states something about mmaping a file so that it can be compressed at once. what exactly does that mean?

**edit**

i wrote this function up real quick, but it doesnt work. it creates the file, and inserts data, put, the data isn't uncompressed correctly when opened with winzip (which can uncompress gziped files), so im wondering whatim doing wrong...

int zcmpr(const char* filename){    char fname2[strlen(filename) + 4];    FILE * ufile;    gzFile cfile;    char buffer[256];    char c;    int i = 0;    ufile = fopen(filename, "r");        if (ufile == NULL) {        perror("Error opening file");        return 0;    }          while (!feof(ufile)) {        c = fgetc(ufile);        buffer = c;    }    fclose(ufile);    strcpy(fname2, filename);    strcat(fname2, ".gz");       cfile = gzopen(fname2, "wb");    gzputs(cfile, buffer);    gzclose(cfile);        return 1;}

[Edited by - relpats_eht on September 26, 2004 5:11:37 PM]

##### Share on other sites
Zlib Manual

1. Open a gzFile with gzopen.
2. If that succeeded, create a file stream (not gz) to write to.
3. Choose a heuristic size of your write chunk.
4. Create an unsigned int buffer with the write chunk. You can use calloc to create the buffer and unsigned int for the type.
5. Use gzread by passing in the gzFile of the compressed file, the pointer to the buffer, and the chunk size you wish to read.
6. Check the return value of the gzread and if it is not the same as your read size, see if it is -1 or 0. If it is -1, then the read failed; clean up. If it is 0 then you reached EOF or the file size is 0. Otherwise it is at EOF and you could only read the returned size.
7. Write the returned size to the output file.
8. Repeat 5 through 7 until 6 returns 0.

##### Share on other sites
I don't know about zlib so much, but mmapping means that the file is mapped into memory. So after you have mmapped a file to a memory, you will have a pointer to a memory region where your file starts and you can begin reading/writing, like you would when using "normal" pointers. On linux (possibly on all POSIX compliant systems) the instruction (one of them) is called (supprise supprise) mmap. Try typing "info mmap". You'll get Memory Mapped I/O section of libc.info.

##### Share on other sites
Here's a quick example, may not work but you should get the general idea of how to do things.

bool CompressFile(const std::string &InFile, const std::string &OutFile){  //these are the compressed and uncompressed sizes of the file  uLongf g_CompSize;  uLongf g_OrigSize;  //buffers to store compressed and orginal data  void *g_CompDataBuff = NULL;  void *g_OrigDataBuff = NULL;  //open the files  FILE *g_InFilePtr = fopen(InFile.c_str());  FILE *g_OutFilePtr = fopen(OutFile.c_str());  //get filesize of original file, there's probably a better way  //to do this.  fseek(g_InFilePtr, 0, SEEK_END);  g_OrigSize = ftell(g_InFilePtr);  rewing(g_InFilePtr);  //allocate the buffer then read the data in  g_OrigDataBuff = malloc(g_OrigSize);  fread(g_OrigDataBuff, g_OrigSize, 1, g_InFilePtr);  //compress the data  g_CompDataBuff = malloc((g_OrigSize + (g_OrigSize * 0.1) + 12));  compress2((Bytef*)g_CompDataBuff, &g_CompSize, (const Bytef*)g_OrigDataBuff, Z_BEST_COMPRESSION);  //write the compressed data to the output file  fwrite(g_CompDataBuff, g_CompDataSize, 1, g_OutFilePtr);  //cleanup  free(g_OrigDataBuff);  free(g_CompDataBuff);  fclose(g_InFilePtr);  fclose(g_OutFilePtr);  return true;}

There's probably a few errors in there but as I've just hacked together that function by ripping pieces from different source I've got on my HD but it does work, you'll wanna add in error checking which I have missed out to make it more readable.

It's a bit of a memory hog as it reads and compresses the file in one go, there is alternate ways to this by using the stream based compression methods, these are a bit more complicated to use but do have the advantage of being able to read in and compress a file in arbitrary sized chunks.

##### Share on other sites
thanx for all the help. i ended up modifying my code to make something taht works, even if it could be improved memory wise, it still works, so im happy.

int zcmpr(const char* filename){    char fname2[strlen(filename) + 4];    FILE * ufile;    gzFile cfile;    char buffer[256];    long fsize;    char c;    int i = 0;    strcpy(fname2, filename);    strcat(fname2, ".gz");    ufile = fopen(filename, "rb");    cfile = gzopen(fname2, "wb");        if (ufile == NULL || cfile == NULL) {        perror("Error opening file");        return 0;    }        fseek(ufile, 0, SEEK_END);    fsize = ftell(ufile);    rewind (ufile);    for (fsize=fsize; fsize >= 0; fsize-=256) {        if (fsize >= 256) {            fread (buffer, 1, 256, ufile);            gzwrite(cfile, buffer, 256);        } else {              fread (buffer, 1, fsize, ufile);            gzwrite(cfile, buffer, fsize);        }      }            fclose(ufile);    gzclose(cfile);        return 1;}

if anyone has any suggestions as to improving it, however, i would still be appreciative... now on to uncompression. shall certainly be much easier now that i know what im doing.

##### Share on other sites
fread will return the amount of data read. When you get to the end of the file, you might not have read a block of 256. You might want to gzwrite only the amount you read.

##### Share on other sites
i do. i find out the length of the file, then, in the for loop, write to the gz file 256 chars at a time, checkign if their are 256 chars left by subtrsacting from the filesize every time, if their arent 256 chars left, it just writes whatevers left by using whatever number remains in fsize...

##### Share on other sites
That works unless the file is growing as you read it.

• 18
• 29
• 11
• 21
• 16