Skip to main content
Email Password   helpLost your password?

Introduction

This article presents two zipped STL iostream implementation based on the library zlib (see download link above) and bzip2 (see download link above). This means that you can easily manipulate zipped streams like any other STL ostream/istream.

To give you an idea, consider following snippet that prints "Hello World":

ostringstream output_buffer;
// writing data

output_buffer<<"Hello world"<<endl 

Now, the same snippet but with zipped output using zlib:

// zip_ostream uses output_buffer as output buffer :)

zip_ostream zipper( output_buffer );

// writing data as usual

zipper<<"Hello world"<<endl 

or using bzip2:

// zip_ostream uses output_buffer as output buffer :)

bzip2_ostream bzipper( output_buffer );

// writing data as usual

bzipper<<"Hello world"<<endl 

As you can see adding zipped buffers into your existing applications is quite straightforward. To summarize, let's see some quick facts about zipstream and bzip2stream:

Why another wrapper? Why not use gzstream?

Writing wrappers around the zlib library is popular on CodeProject. If you search for 'zip' you will find at least 14 articles on the topic. Moreover, if you crawl on the web and especially on zlib home page, you can find dozens of other wrappers.

So why another wrapper? Well, none of the wrappers are fully STL compliant. Ok, this is not true since gzstream (see download link above) implements fstream-like STL streams. However, gzstream has three drawbacks:

  1. It does not allow buffer to buffer compression since it is based on gzip i/o methods: only file to buffer or buffer to file are supported,
  2. it is licensed under LGPL which makes it difficult to use in commercial apps,
  3. it does not support wchar_t

Last reason to write this wrapper: it is a good exercise to understand and implement iostreams.

Wrapper architecture

The three drawbacks of gzstream pushed me to re-implement an STL wrapper for zlib (and later on, do some cut and paste to get bzip2 working).

This wrapper takes a user defined i/ostream to write or read compressed data. This approach is quite flexible since the user can give any stream (istringstream, ifstream, or custom stream) to store or load the compressed data.

Internally zip_stream acts as a triple buffer: the streambuf object in itself, zlib library and the user-defined stream. For example, during the compression process, the buffers are used:

Some care must be taken when flushing: you must use the method zflush that will first flush the streambuf, then flush the zlib buffer, then flush the user-defined stream. Note that you should avoid flushing as it degrades compression.

Implementing iostreams

Since I'm not an STL expert, I will very briefly discuss this part. There's room for a tutorial on this topic...

To implement custom iostream, you need to take the following steps:

Class quick reference

All the zlib classes are in the zlib_stream namespace and all the bzip2 classes are in the bzip2_stream namespace.

The two main classes of the zlib wrapper are basic_zip_ostream and basic_zip_istream which implement respectively compression and decompression and behave like classic basic_ostream and basic_istream.

Classical typedef are also provided for these classes:

The bzip2 classes have similar names, just replace zlib by bzip2: basic_zip_streambuf becomes basic_bzip2_streambuf.

basic_zip_ostream

This class inherits from basic_ostream:

template<
    typename Elem, 
    typename Tr = char_traits<Elem;>,
    typename ElemA = std::allocator<Elem>,
    typename ByteT = unsigned char,
    typename ByteAllocatorT = std::allocator<ByteT> 
    >
basic_zip_ostream : public basic_ostream<Elem, Tr>

where

Constructor

basic_zip_ostream( 
    ostream_reference ostream_, 
    bool is_gzip_ = false,
    size_t level_ = Z_DEFAULT_COMPRESSION,
    EStrategy strategy_ = DefaultStrategy,
    size_t window_size_ = 15,
    size_t memory_level_ = 8,
    size_t buffer_size_ = 4096
);

Note that if you choose the gzip option, a header will be automatically added in the constructor and the gzip footer (CRC + data size) will be added in the destructor.

Other methods

Predefined typedefs

typedef basic_zip_ostream<char> zip_ostream;
typedef basic_zip_ostream<wchar_t> zip_wostream;

basic_zip_istream

This class inherits from basic_istream:

template<
    typename Elem, 
    typename Tr = char_traits<Elem;>,
    typename ElemA = std::allocator<Elem>,
    typename ByteT = unsigned char,
    typename ByteAT = std::allocator<ByteT> 
    >
basic_zip_istream : public basic_istream<Elem, Tr>

Constructor

basic_zip_istream( 
    istream_reference istream_, 
    size_t window_size_ = 15,
    size_t read_buffer_size_ = 1024 * 10,
    size_t input_buffer_size_ = 1024 * 5
)

Other methods

Predefined typedefs

typedef basic_zip_istream<char> zip_istream;
typedef basic_zip_istream<wchar_t> zip_wistream;

How to ...

All the following examples are valid for both zlib and bzip2 wrappers.

Compress to a buffer

ostringstream buffer;
zip_ostream zipper(buffer);

// writing stuff

zipper<<...

//flushing VERY IMPORTANT!

zipper.zflush();

// buffer.str() is ready

Compress to a file

ofstream file("test.zip",ios::out | ios::binary);
{
zip_ostream zipper(file, true /* gzip file*/);

// writing stuff

zipper<<...

} // the stream is flushed, the destructor is called and gzip header appended

// the file is ready

Decompress from a buffer

istringstream buffer;
zip_istream unzipper(buffer);

// reading stuff

unzipper>>...

Decompress from a file

ifstream file("test.zip", ios::in | ios::binary);
zip_istream unzipper(file);

// reading stuff

unzipper>>...

// if the file was gzip, we can check the crc

if (unzipper.is_gzip())
    std::cout<<"crc check: "<<( unzipper.check_crc() ? "ok" : "failed");

Using it in your project

Zlib wrapper

bzip2 wrapper

History

Reference

License

These zlib and bzip2 wrappers are licensed under the zlib/libpng license.

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
Questionzipstream.hpp and zipstream.ipp? Pin
dbbtvlzfpz
12:30 27 Oct '08  
AnswerRe: zipstream.hpp and zipstream.ipp? Pin
Tux`
10:45 1 Apr '09  
GeneralFixes for modern STL (gcc 4) Pin
NoGoodNicks
9:58 6 Oct '07  
Generalzipstream is not necessary anymore, you can use the boost::iostreams lib instead Pin
herculon
3:30 27 Jan '06  
Generalzipstream with boost::archive Pin
jhsy
20:12 11 Aug '05  
GeneralRe: zipstream with boost::archive Pin
herculon
4:47 12 Aug '05  
Generalsmall comment on namespace Pin
jhsy
19:40 11 Aug '05  
Generalbzip2stream file <-> file works fine, zipstream file2file fails. Pin
herculon
10:07 25 Jul '05  
Generalworking on linux? Pin
dekim
13:06 19 May '05  
GeneralRe: working on linux? Pin
Anonymous
16:13 8 Jun '05  
GeneralRe: working on linux? Pin
irotas
18:09 28 Oct '05  
GeneralReading zipped file?? Pin
Robert Bielik
3:51 28 Apr '05  
GeneralProblem --Stream and ZipStream are in same scope Pin
takuni
20:01 3 Feb '05  
Generalbzip2stream fails with wide file streams Pin
Denis Dubrov
10:05 7 Jan '05  
Generalsupport for seekg/tellg? Pin
greglandrum
12:42 1 Dec '04  
Generalzipstream cannot unzip the zipped file Pin
lost in templates
17:01 20 Oct '04  
GeneralHow to compress Huge Memory Buffer ? Pin
WanaDev
18:15 11 Feb '04  
GeneralZlib Wrapper and GZip generated buffer on IIS Pin
Anonymous
17:39 10 Feb '04  
GeneralCompiling with VC6 Pin
Marlon Gaspar
9:43 26 Jan '04  
GeneralRe: Compiling with VC6 Pin
Vattila
7:04 13 Mar '04  
GeneralRe: Compiling with VC6 Pin
Vattila
17:10 15 Mar '04  
GeneralRe: Compiling with VC6 Pin
Jonathan de Halleux
21:36 15 Mar '04  
GeneralRe: Compiling with VC6 Pin
Patrik Müller
0:46 24 Aug '04  
GeneralRe: Compiling with VC6 Pin
Anonymous
23:13 24 Aug '04  
GeneralRe: Compiling with VC6 Pin
Patrik Müller
22:14 25 Aug '04  


Last Updated 2 Oct 2003 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2009