Decompressing a GZip Stream with Zlib

Decompressing a GZip Stream with Zlib

    Decompressing a GZip Stream with Zlib
    Contents

        Introduction
        Download
        Source
        Related Links

    Introduction

    This C++ program reads a file named input.txt.gz into memory, then uses the zlib library to decompress and print the data. After uncompression, the lyrics to Rick Astley's Never Gonna Give You Up will be printed.

    Some things to note:

        The input.txt.gz file was generated using 7-zip by compressing input.txt (this file is also included in the download).
        The zipped file supplied contains a Code::Blocks project file and was written and tested under Windows using MinGW only.
        The necessary zlib files are included. They were obtained from the official zlib website. zdll.lib was renamed to libzdll.a in order to make it work with MinGW.

    Download

    You may download the source code and Code::Blocks project files here.

    Download Source

    Source

    Here is the source code listing for the program.
    view plaincopy to clipboardprint?

        /*
        This C++ program uses zlib to read then decompress a gzipped file in memory.
        Author: Andrew Lim Chong Liang
        http://windrealm.org
        */ 
        #include <cstdio> 
        #include <string> 
        #include <cstring> 
        #include <cstdlib> 
        #include "zlib.h" 
        #include "zconf.h" 
        using namespace std; 
         
        bool gzipInflate( const std::string& compressedBytes, std::string& uncompressedBytes ) { 
          if ( compressedBytes.size() == 0 ) { 
            uncompressedBytes = compressedBytes ; 
            return true ; 
          } 
         
          uncompressedBytes.clear() ; 
         
          unsigned full_length = compressedBytes.size() ; 
          unsigned half_length = compressedBytes.size() / 2; 
         
          unsigned uncompLength = full_length ; 
          char* uncomp = (char*) calloc( sizeof(char), uncompLength ); 
         
          z_stream strm; 
          strm.next_in = (Bytef *) compressedBytes.c_str(); 
          strm.avail_in = compressedBytes.size() ; 
          strm.total_out = 0; 
          strm.zalloc = Z_NULL; 
          strm.zfree = Z_NULL; 
         
          bool done = false ; 
         
          if (inflateInit2(&strm, (16+MAX_WBITS)) != Z_OK) { 
            free( uncomp ); 
            return false; 
          } 
         
          while (!done) { 
            // If our output buffer is too small 
            if (strm.total_out >= uncompLength ) { 
              // Increase size of output buffer 
              char* uncomp2 = (char*) calloc( sizeof(char), uncompLength + half_length ); 
              memcpy( uncomp2, uncomp, uncompLength ); 
              uncompLength += half_length ; 
              free( uncomp ); 
              uncomp = uncomp2 ; 
            } 
         
            strm.next_out = (Bytef *) (uncomp + strm.total_out); 
            strm.avail_out = uncompLength - strm.total_out; 
         
            // Inflate another chunk. 
            int err = inflate (&strm, Z_SYNC_FLUSH); 
            if (err == Z_STREAM_END) done = true; 
            else if (err != Z_OK)  { 
              break; 
            } 
          } 
         
          if (inflateEnd (&strm) != Z_OK) { 
            free( uncomp ); 
            return false; 
          } 
         
          for ( size_t i=0; i<strm.total_out; ++i ) { 
            uncompressedBytes += uncomp[ i ]; 
          } 
          free( uncomp ); 
          return true ; 
        } 
         
        /* Reads a file into memory. */ 
        bool loadBinaryFile( const std::string& filename, std::string& contents ) { 
          // Open the gzip file in binary mode 
          FILE* f = fopen( filename.c_str(), "rb" ); 
          if ( f == NULL ) 
            return false ; 
         
          // Clear existing bytes in output vector 
          contents.clear(); 
         
          // Read all the bytes in the file 
          int c = fgetc( f ); 
          while ( c != EOF ) { 
            contents +=  (char) c ; 
            c = fgetc( f ); 
          } 
          fclose (f); 
         
          return true ; 
        } 
         
        int main() { 
          // Read the gzip file data into memory 
          std::string fileData ; 
          if ( !loadBinaryFile( "input.txt.gz", fileData ) ) { 
            printf( "Error loading input file." ); 
            return 0 ; 
          } 
         
          // Uncompress the file data 
          std::string data ; 
          if ( !gzipInflate( fileData, data ) ) { 
            printf( "Error decompressing file." ); 
            return 0 ; 
          } 
         
          // Print the data 
          printf( "Data: \"" ); 
          for ( size_t i=0; i<data.size(); ++i ) { 
            printf( "%c", data[i] ); 
          } 
          printf ( "\"\n" ); 
          return 0; 
        } 

    Related Links

        Deusty Gzip compression/decompression - Objective-C version
        StackOverflow: How can I decompress a gzip stream with zlib?


原文地址:https://www.cnblogs.com/lexus/p/2991659.html