Getting Started with ZipStream

The ZipStream component may be used to compress or decompress data from a stream. In the .NET and Java editions of IPWorks Zip, streams can be directly set as input and output. In all other editions, data can be read in blocks (chunks) and compressed or decompressed as it becomes available. This guide will cover the basics of using the ZipStream component in both of these ways.

ZipStream offers multiple ways to operate upon the stream data. The StreamFormat property specifies the algorithm to use. Possible values are:

  • Deflate
  • Zlib
  • Gzip

ZipStream in .NET and Java

The ZipStream component operates by producing streams that read or write compressed data, as appropriate. The GetDecompressionStream and GetCompressionStream methods return a stream from which the component will read data, and take as a parameter the stream to which the component will write data.

For additional ease of use, the CompressData and DecompressData methods are also provided to compress or decompress byte arrays with a single line of code.

Using GetCompressionStream

The GetCompressionStream method returns a stream to which uncompressed data should be written, and takes as a parameter the stream to which the component will write compressed data. Here are some examples.

.NET: Zipstream zipstream1 = new Zipstream(); zipstream1.StreamFormat = ZipstreamStreamFormats.sfDeflate; //create filestream that the component will use to write compressed data System.IO.FileStream compressedData = new System.IO.FileStream(filename, FileMode.Create); //get stream that the component will use to read uncompressed data from System.IO.Stream uncompressedData = zipstream1.GetCompressionStream(compressedData); uncompressedData.Write(dataBytes, 0, dataBytes.length);

Java: Zipstream zipstream1 = new Zipstream(); zipstream1.SetStreamFormat(0); //Deflate //create filestream that the component will use to write compressed data java.IO.FileInputStream compressedData = new java.IO.FileInputStream(file); //get stream that the component will use to read uncompressed data from java.IO.BufferedOutputStream uncompressedData = zipstream1.GetCompressionStream(compressedData); uncompressedData.Write(dataBytes, 0, dataBytes.length);

Using GetDecompressionStream

The GetDecompressionStream method returns a stream to which compressed data should be written, and takes as a parameter the stream to which the component will write decompressed data. Here are some examples.

.NET: Zipstream zipstream1 = new Zipstream(); zipstream1.StreamFormat = ZipstreamStreamFormats.sfDeflate; //create filestream that the component will use to write decompressed data System.IO.FileStream decompressedData = new System.IO.FileStream(filename, FileMode.Create); //get stream that the component will use to read compressed data from System.IO.Stream compressedData = zipstream1.GetCompressionStream(decompressedData); compressedData.Write(compressedDataBytes, 0, compressedDataBytes.length);

Java: Zipstream zipstream1 = new Zipstream(); zipstream1.SetStreamFormat(0); //Deflate //create filestream that the component will use to write decompressed data java.IO.FileInputStream decompressedData = new java.IO.FileInputStream(file); //get stream that the component will use to read compressed data from java.IO.BufferedOutputStream compressedData = zipstream1.GetCompressionStream(decompressedData); compressedData.Write(compressedDataBytes, 0, compressedDataBytes.length);

Using CompressData

The CompressData method should be used when all of the uncompressed data is available ahead of time. First set InputData to the uncompressed data; if the data is in binary format, InputDataB should be used instead. Then call CompressData, and access the compressed data through OutputData or the raw binary compressed data through OutputDataB. Here are some examples.

.NET: zipstream1.InputData = fullUncompressedData; zipstream1.CompressData(); string fullCompressedData = zipstream1.OutputData;

Java: zipstream1.SetInputData(fullUncompressedData); zipstream1.CompressData(); string fullCompressedData = zipstream1.GetOutputData();

In addition to OutputData, the compressed data may also be accumulated within the CompressedData event.

Using DecompressData

The DecompressData method should be used when all of the compressed data is available ahead of time. Fisrt set InputData to the compressed data; if the data is in binary format, InputDataB should be used instead. Then call DecompressData, and access the decompressed data through OutputData or the raw binary decompressed data through OutputDataB. Here are some examples.

.NET: zipstream1.InputData = fullCompressedData; zipstream1.DecompressData(); string fullDecompressedData = zipstream1.OutputData;

Java: zipstream1.SetInputData(fullCompressedData); zipstream1.DecompressData(); string fullDecompressedData = zipstream1.GetOutputData();

In addition to OutputData, the decompressed data may also be accumulated within the DecompressedData event.

ZipStream in Other Editions: Delphi, C++, etc.

CompressBlock and DecompressBlock

The CompressBlock and DecompressBlock methods operate on blocks (chunks) of data. The methods may be used to compress and decompress data as it becomes available.

Note that when using blocks of data the OutputData property is not applicable. Instead data is made available through the CompressedData and DecompressedData events.

If all data is available ahead of time CompressData and DecompressData may be called instead.

Using CompressBlock

First set InputData to the current block to be compressed; if the data is in binary format, InputDataB should be used instead. Next call CompressBlock to compress the current block. Note that CompressBlock takes a LastBlock parameter. If the block of data is the final block to be compressed set this to True. For all other blocks set this to False.

During compression the CompressedData event will fire with the compressed data. Inside the CompressedData event, the string-encoded compressed data is available through the Data event parameter, and the raw binary data is available through the CompressedDataDataB property. Note that this event may not fire for every call to CompressBlock due to the way the compression algorithm operates.

Note that OutputData is not applicable when compressing block data.

Here are some examples of reading blocks of data from a stream and compressing them. Note that the BytesRemaining, FetchDataBlock, and DoSomethingWith functions are intended to be placeholders for custom methods that depend on the specifics of the application.

Delphi: //In the main flow of the program while (BytesRemaining(stream)) do begin ipzZipStream1.InputDataB := FetchDataBlock(stream); if BytesRemaining(stream) then ipzZipStream1.CompressBlock(False) else //last block ipzZipStream1.CompressBlock(True); end; //Inside the CompressedData event handler: procedure TFormZipStream.OnCompressedData(Sender: TObject; Data: String); begin //CompressedDataDataB is the binary equivalent of the Data event parameter DoSomethingWith(ipzZipStream1.CompressedDataDataB); end;

C++: //In the main flow of the program MyZipStream zipstream; while (BytesRemaining(stream)) { char* data = FetchDataBlock(stream); zipstream.SetInputData(data, strlen(data)); if (BytesRemaining(stream)) zipstream.CompressBlock(0); else //last block zipstream.CompressBlock(1); } //In the CompressedData event handler: virtual int FireCompressedData(ZipStreamCompressedDataEventParams *e) { DoSomethingWith(e->Data); return 0; }

Using DecompressBlock

First set InputData to the current block to be decompressed; if the data is in binary format, InputDataB should be used instead. Next call DecompressBlock to decompress the current block.

During decompression the DecompressedData event will fire with the decompressed data. Inside the DecompressedData event, the string-encoded decompressed data is available through the Data event parameter, and the raw binary data is available through the DecompressedDataDataB property. Note that this event may not fire for every call to DecompressBlock due to the way the decompression algorithm operates.

Note that OutputData is not applicable when decompressing block data.

Here are some examples of reading blocks of compressed data from a stream and decompressing them. Note that the BytesRemaining, FetchDataBlock, and DoSomethingWith functions are intended to be placeholders for custom methods that depend on the specifics of the application.

Delphi: //In the main flow of the program while (BytesRemaining(stream)) do begin ipzZipStream1.InputDataB := FetchDataBlock(stream); if BytesRemaining(stream) then ipzZipStream1.DecompressBlock(False) else //last block ipzZipStream1.DecompressBlock(True); end; //Inside the DecompressedData event handler: procedure TFormZipStream.OnDecompressedData(Sender: TObject; Data: String); begin //DecompressedDataDataB is the binary equivalent of the Data event parameter DoSomethingWith(ipzZipStream1.DecompressedDataDataB); end;

C++: //In the main flow of the program MyZipStream zipstream; while (BytesRemaining(stream)) { char* data = FetchDataBlock(stream); zipstream.SetInputData(data, strlen(data)); if (BytesRemaining(stream)) zipstream.DecompressBlock(0); else //last block zipstream.DecompressBlock(1); } //In the DecompressedData event handler: virtual int FireDecompressedData(ZipStreamCompressedDataEventParams *e) { DoSomethingWith(e->Data); return 0; }

CompressData and DecompressData

The CompressData and DecompressData methods operate on the complete blob of data. The entire compressed or decompressed data must be set to InputData before calling either method.

To compress and decompress data in blocks (chunks) see CompressBlock and DecompressBlock.

Using CompressData

First set InputData to the decompressed data. This should be the entire data to be compressed. If the data is in binary format, InputDataB should be used instead. Next call CompressData. After compression OutputData will hold the compressed data, and OutputDataB will hold the compressed data in raw binary form. Here are some examples.

Delphi: //In the main flow of the program ipzZipStream1.InputDataB := entireDataBlob; ipzZipStream1.CompressData(); compressedBinaryData := ipzZipStream1.OutputData;

C++: //In the main flow of the program MyZipStream zipstream; zipstream.SetInputData(entireDataBlob, strlen(entireDataBlob)); zipstream.CompressData(); zipstream.GetOutputData(compressedData, compressedDataLength);

In addition to OutputData, the compressed data may also be accumulated within the CompressedData event.

Using DecompressData

First set InputData to the compressed data; if the data is in binary format, InputDataB should be used instead. This should be the entire data to be decompressed. Next call DecompressData. After decompression OutputData will hold the decompressed data, and OutputDataB will hold the decompressed data in raw binary form. Here are some examples.

Delphi: //In the main flow of the program ipzZipStream1.InputDataB := entireCompressedDataBlob; ipzZipStream1.DecompressData(); decompressedBinaryData := ipzZipStream1.OutputDataB;

C++: //In the main flow of the program MyZipStream zipstream; zipstream.SetInputData(entireCompressedDataBlob, strlen(entireCompressedDataBlob)); zipstream.DecompressData(); zipstream.GetOutputData(decompressedData, decompressedDataLength);

In addition to OutputData, the decompressed data may also be accumulated within the DecompressedData event.

We appreciate your feedback.  If you have any questions, comments, or suggestions about this article please contact our support team at kb@nsoftware.com.