Contents - Index - Previous


Using Streams


 

 

You can perform stream zipping in one of two ways:   Using either standard pkzip archive format or the ZLib format.  The standard PKZip format allows you to store multiple elements into a standard pkzip archive while the ZLib format allows one element to be zipped but does not carry the overhead of all of the pkzip headers.   Here are the pros and cons of each:

 

PKZip Format stream zipping

 

ZLib Format stream zipping

 

For ZLib Format stream zipping see the following:

 

 

PKZip Format Stream Zipping

Zipping and UnZipping to and from streams is as easy as zipping to and from zip files.  This allows your application to read from and save directly to streams as if they were normal files.  You still have full control over all options like encryption, compression level, etc.  

 

One important thing to remember.  You should always set VCLZip's ArchiveStream property back to nil after using it and Free the stream that you pointed it at yourself.  VCLZip will not Free the stream that ArchiveStream points to.

 

The following example shows just how easy it is to do stream to stream compression and decompression.

   

Say you have your data to be compressed in a TMemoryStream.  Pass it into the following to compress it.  The compressed stream will be returned.  

 

function CompressStream(StreamToCompress: TMemoryStream; Filename: String): TMemoryStream; 

begin 

Result := TMemoryStream.Create; 

// Creating new compressed stream 

VCLZip.ArchiveStream := TMemoryStream.Create; 

// Compress the data from uncompressed stream into the ArchiveStream; 

VCLZip.ZipFromStream(StreamToCompress, Filename); 

// Retrieve the resulting compressed stream

Result := VCLZip.ArchiveStream;

// Detach the compressed stream from VCLZip 

VCLZip.ArchiveStream := nil; 

end; 

 

Now you have the returned stream which contains the compressed data.  You can do what you need with this stream.  Now uncompress it into a stream by passing it into the following function.  The decompressed stream will be returned. 

 

function UnCompressStream(StreamToDecompress: TMemoryStream; Filename: String): TMemoryStream; 

begin 

// Point ArchiveStream at the compressed stream 

VCLZip.ArchiveStream := StreamToDecompress; 

// Create stream to uncompress into 

Result := TMemoryStream.Create; 

// Unzip using the same dummy filename as you used to zip it 

VCLZip.UnZipToStream( Result, Filename); 

// We're done with the compressed stream 

VCLZip.ArchiveStream := nil; 

end; 

 

Tip: Using TStreams other than TMemoryStream  

 

You can always use CopyFrom or SaveToStream to put the contents of ArchiveStream into any type of TStream you wish.  Such as

 

VCLZip.ArchiveStream.SaveToStream(yourTBlobStream);

 

However, for increased performance, if are creating a new archive and you use VCLZip properly you can avoid having to copy from one stream to another.  As long as you never perform an operation that causes VCLZip to have to create a temporary stream you can retrieve ArchiveStream directly.  Any operation that causes VCLZip to modify an existing stream causes a temporary stream to be created.

If you are creating a new archive and you are compressing just one file into it, then no temporary file is create.  If you are creating a new archive and you are adding multiple files to the archive, you should use OnGetNextStream to add the additional streams.  This causes VCLZip to add all of the streams in one operation.

If you use the above recommendations then in the above example, you could replace the instances of TMemoryStream with any type of TStream and it should still work.

 

When Using Delphi 4, 5, BCB 4, or BCB5  

 

When using earlier versions of Delphi or BCB, TStreams do not have Int64 capabilities.  For this reason, VCLZip works internally with TkpStreams, which add this capability.  Therefore, when working with Streams, you have the choice of using decendants of TkpHugeStream which is defined in KPHSTRMS.PAS, or using the helper methods that allow you to work with normal TStreams.  Working with TkpHugeStreams is more efficient and, if you normally work with TFileStreams or TMemoryStreams, it is just as easy to work with TkpFileStream and TkpMemoryStream types.as they have the same properities and methods as their TStream counterparts.  For instance, in the above example you just need to change the instances of TMemoryStream to TkpMemoryStream and that is all the change that is necessary. 

 

However, if you need to work with other TStream decendants like TBlobStream or TStringStream, if you don't want to define your own similar decendants to TkpHugeStream, you can just slightly modify the code to use the overloaded methods of VCLZip.  They are:

 

 

So the above example might look something like this instead, if you were working with TStringStreams, when using earlier versions of Delphi/BCB:

 

function CompressStream(StreamToCompress: TStringStream; Filename: String): TStringStream; 

begin 

      // Use TkpMemoryStream instead for initial zipping.  We'll get the

      // compressed data back in a TStringStream after compressing

VCLZip.ArchiveStream := TkpMemoryStream.Create;

// Compress the data from uncompressed stream into the ArchiveStream;

//Overloaded version of ZipFromStream will be used 

VCLZip.ZipFromStream(StreamToCompress, Filename); 

// Retrieve your compressed TStringStream

VCLZip.ArchiveStream.SaveToStream(Result);

VCLZip.ArchiveStream.Free;  // Need to do this when done

// Detach your compressed stream from VCLZip 

VCLZip.ArchiveStream := nil; 

end; 

 

Now you have the returned stream which contains the compressed data.  You can do what you need with this stream.  Now uncompress it into a TStringStream by passing it into the following function.  The decompressed stream will be returned.  

 

function UnCompressStream(StreamToDecompress: TStringStream; Filename: String): TStringStream; 

begin 

// Point ArchiveStream at the compressed stream

// Use the special SetArchiveTStream method

VCLZip.SetArchiveTStream(StreamToDecompress); 

// Create stream to uncompress into 

Result := TMemoryStream.Create; 

// Unzip using the same dummy filename as you used to zip it 

// Overloaded version of UnZipToStream will be used

VCLZip.UnZipToStream( Result, Filename); 

VCLZip.ArchiveStream.Free;   // Need to do this

// Done with the compressed stream 

VCLZip.ArchiveStream := nil; 

end;