Jump to content


Check out our Community Blogs

Register and join over 40,000 other developers!


Recent Status Updates

View All Updates

Photo
- - - - -

Compress and Decompress with ZLib Library

delphi zlib compression decompression

  • Please log in to reply
No replies to this topic

#1 Luthfi

Luthfi

    CC Leader

  • Expert Member
  • PipPipPipPipPipPipPip
  • 1320 posts
  • Programming Language:PHP, Delphi/Object Pascal, Pascal, Transact-SQL
  • Learning:C, Java, PHP

Posted 20 July 2013 - 09:14 AM

Overview
 

Sometimes we need to compress our data, either to reduce network traffic when transmitting or just to save space in storage media. Lucky for us, Delphi has provided ready to use compression/decompression library. This library was a wrapper around zlib open source project.

 

Delphi wraps the zlib library into two TStream descendant classes. TCompressionStream and TDecompressionStream. As the names suggested, TCompressionStream is for compressing and TDecompressionStream is for decompressing. To use either TStream class you would need to include zlib.pas unit in your uses list.

 

 

Compressing

 

TCompressionStream is a write only TStream descendant. Therefore, you can only write data to its instance. In its constructor you must pass another TStream instance that will get the result of compression.

 

For example, if you want to compress some data into memory (in this example we will use TMemoryStream), we should setup the TCompressionStream instance like below.

...
uses
  ...
  , zlib
  ...
  ;

...

var
  vMem: TStream;
  vCompressor: TStream;
begin
  vMem := TMemoryStream.Create;
  try
    vCompressor := TCompressionStream.Create(clMax, vMem);
    try
  ...
end;

Note:

  clMax specifies the compression level.

 

The actual compressing process is done by feeding data from the source to the TCompressionStream. In the above example context, if we want to compress content of stream, we could do like this.

var
  ...
  B: array[1..2048] of byte;
  R: integer;
  vSrc: TStream;
  ...
begin
  ...
  repeat
    R := vSrc.Read(B, SizeOf(B));
    if R > 0 then
      vCompressor.Write(B, R);
   until R < SizeOf(B);
   ...
end;

When the above code finished, vMem will hold the compressed data.

 

Some of you might think the code in repeat-until block could be simplified into

  vCompressor.CopyFrom(vSrc, 0);

But actually this one liner is not that reliable. Because CopyFrom method relies on the size of the source stream. And in some TStream class, reading the size will move the internal pointer to the end of the stream which might render the actual copying process fails because it thought that it already reached the last byte in the source stream. So, while in most cases CopyFrom will work fine, but not on all cases. Therefore let's pick the safer route.

 

And here is a complete working code for compressing content of a file to another file.

procedure Compress(const ASrc, ADest: string);
var
  B: array[1..2048] of byte;
  R: Integer;
  vSrc: TStream;  // source file stream
  vDest: TStream;  // destination file stream
  vCompressor: TStream;  // compression stream
begin
  if not FileExists(ASrc) then
    raise Exception.Create('Source file does not exist');

  vDest := TFileStream.Create(ADest, fmCreate);
  try
    vCompressor := TCompressionStream.Create(clMax, vDest);
    try
      vSrc := TFileStream.Create(ASrc, fmOpenRead);
      try
        repeat
          R := vSrc.Read(B, SizeOf(B));
          if R > 0 then
            vCompressor.Write(B, R);
        until R < SizeOf(B);
//        C.CopyFrom(S, 0);
      finally
        vSrc.Free;
      end;
    finally
      vCompressor.Free;
    end;
  finally
    vDest.Free;
  end;
end;

Decompressing

 

As the opposite of TCompressionStream, TDecompressionStream is read-only TStream descendant. No writing data to the instance of this class, or you will get exception. But similar with TCompressionStreamTDecompressionStream constructor also requires you to supply a TStream instance that supplies the data to be decompressed.

 

For example, if you want to decompress a file and the content of this file is contained in a TFileStream instance named vSrcFile, then you need to instantiate your TDecompressionStream like this.

vDecompressor := TDecompressionStream(vSrcFile);

The actual decompressing process is done when reading from the decompressor stream into the destination of your choice. Something like this.

repeat
  R := vDecompressor.Read(B, SizeOf(B));
  if R > 0 then
    vDest.Write(B, R);
until R < SizeOf(B);

Note that in the above code, vDest is a TStream instance.

 

And here is a complete working code to decompress the content of compressed file (of course only files compressed by zlib) into another file.

procedure TForm1.Decompress(const ASrc, ADest: string);
var
  B: array[1..2048] of byte;
  R: Integer;
  vSrc: TStream;  // source file stream
  vDest: TStream;  // destination file stream
  vDecompressor: TStream;  // compression stream
begin
  if not FileExists(ASrc) then
    raise Exception.Create('Source file does not exist');

  vSrc := TFileStream.Create(ASrc, fmOpenRead);
  try
    vDecompressor := TDecompressionStream.Create(vSrc);
    try
      vDest := TFileStream.Create(ADest, fmCreate);
      try
        repeat
          R := vDecompressor.Read(B, SizeOf(B));
          if R > 0 then
            vDest.Write(B, R);
        until R < SizeOf(B);
      finally
        vDest.Free;
      end;
    finally
      vDecompressor.Free;
    end;
  finally
    vSrc.Free;
  end;
end;

Demo Project

 

I have written a demo project to show how to do compression and decompression. The demo project will compress a file to another file, and also decompress a file. Here is full source code of the demo project: Attached File  Demo.zip   237.59KB   3198 downloads. Feel free to use the codes for anything you want.

 

Upon running the demo project, you will get something like shown below.

RunTime.png

 

Now just click Compress! button to compress the selected source file to the specied target file. After that, you can decompress the compressed file to another file. Finally you can inspect the result of decompression, and compare it to the original file. When both are exactly the same, then our codes are working correctly.

 

Enjoy!


  • 0





Also tagged with one or more of these keywords: delphi, zlib, compression, decompression

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download