|
||
This document describes how to use the EZLib library to compress and decompress files, file archive, and memory streams. The files can be compressed to ZIP and GZIP formats and decompressed from the same using the EZLib library.
EZLib is a compression library based on Version 1.2.3 of Zlib. Zlib is a freeware library available to download from the Zlib website. It is written in C and hence exports a C interface. EZLib provides C++ wrapper classes that encapsulate the functionality of Zlib. These classes simplify the use of the compression library.
EZLib allows clients to compress and decompress data from files and buffers. These tasks are performed iteratively by calling the compression or decompression functions until the required task is complete. Clients must respond to callbacks from the library to provide information and resources required to complete the task.
The EZLib library supports two file formats as shown below:
Zip format
GZIP format
The CEZCompressor
class provides memory stream
compression and decompression functions, while performing integrity checks on
the compressed/uncompressed data.
The compression of memory streams can be performed in single or
multiple steps based on the size of the buffer. Compression is done for a small
buffer in a single step by calling the CompressL()
function for small memory bits. Larger memory buffers can be compressed by
repeatedly calling the DeflateL()
function until the
entire buffer is compressed to the target buffer.
The decompression of memory streams can be performed using the
DecompressL()
function or by calling
InflateL()
repeatedly until the source data is
decompressed to the target buffer.
Compression and decompression can be performed on two file formats:
Zip files
Gzip files
The compression of a file into a zip file can be achieved by specifying
the input and output files, together with other compression parameters as shown
in the example code below. The CEZFileBufferManager
class
provides functions that accept the input and output files as parameters and
converts the data into buffers for MEZBufferManager
class
to manage it internally. Then this buffer is passed with other compression
parameters to the object of the CEZCompressor
class. The
client then calls the DeflateL()
function iteratively
until the zip file is created.
/*
* Compresses the file into a Zip file using the EZlib component.
* It is assumed that the input and output file names are contained in a
* provided ini file.
*/
void CEZlibEZipTests::DoEZlibDeflateL()
{
//Open input file
_LIT(KInputFile, "c:\\private\\E80000B7\\zip\\input\\Ezlib.doc");
TFileName inputFile(KInputFile);
RFile input;
err = input.Open(iRfs, inputFile, EFileStream | EFileRead | EFileShareExclusive);
if(err != KErrNone)
{
INFO_PRINTF1(KOpenFileError);
User::Leave(err);
}
CleanupClosePushL(input);
//open output file
_LIT(KOutputFile, "c:\\private\\E80000B7\\zip\\input\\Ezlib.zip");
TFileName outputFile(KOutputFile);
RFile output;
err = output.Replace(iRfs, outputFile, EFileStream | EFileWrite | EFileShareExclusive);
if(err != KErrNone)
{
INFO_PRINTF1(KCreateFileError);
User::Leave(err);
}
CleanupClosePushL(output);
CEZFileBufferManager *bufferManager = CEZFileBufferManager::NewLC(input, output);
CEZCompressor *compressor = CEZCompressor::NewLC(*bufferManager, aLevel, aWindowBits, aMemLevel, aStrategy);
while(compressor->DeflateL())
{
}
CleanupStack::PopAndDestroy(4);
CEZFileBufferManager *bufferManager = CEZFileBufferManager::NewLC(input, output);
CEZCompressor *compressor = CEZCompressor::NewLC(*bufferManager, aLevel, aWindowBits, aMemLevel, aStrategy);
while(compressor->DeflateL())
{
}
}
The decompression of the zip file is performed similarly by passing the
input and output file to an instance of the
CEZFileBufferManager
class. This converts the data into
memory streams, internally managed by the MEZBufferManager
class. The buffer is then passed to the object of the
CEZDecompressor
class. The client then calls the
InflateL()
function repeatedly until the decompression is
complete. The following code demonstrates the decompression scenario.
/* Decompresses the file contained in a Zip file using the EZlib component.
* It is assumed that the input and output file names are contained in a
* provided ini file.
*/
void CEZlibEZipTests::DoEZlibInflateL()
{
//Open input file
_LIT(KInputFile, "c:\\private\\E80000B7\\zip\\input\\Ezlib.zip");
TFileName inputFile(KInputFile);
RFile input;
err = input.Open(iRfs, inputFile, EFileStream | EFileRead | EFileShareExclusive);
if(err != KErrNone)
{
INFO_PRINTF1(KOpenFileError);
User::Leave(err);
}
CleanupClosePushL(input);
//open output file
_LIT(KOutputFile, "c:\\private\\E80000B7\\zip\\input\\Ezlib.doc");
TFileName outputFile(KOutputFile);
RFile output;
err = output.Replace(iRfs, OutputFile, EFileStream | EFileWrite | EFileShareExclusive);
if(err != KErrNone)
{
INFO_PRINTF1(KCreateFileError);
User::Leave(err);
}
CleanupClosePushL(output);
CEZFileBufferManager *bufferManager = CEZFileBufferManager::NewLC(input, Output);
CEZDecompressor *decompressor = CEZDecompressor::NewLC(*bufferManager, aWindowBits);
while(decompressor->InflateL())
{
}
CleanupStack::PopAndDestroy(4);
}
The process of compressing a file to a Gzip file can be carried out by
passing the uncompressed file along with the name of the target GZip file to an
instance of the CEZFileToGZip
class. The client then uses
the DeflateL()
function to compress the file to the
required format. The code below explains the compression procedure.
/*
* Compresses a file to a GZip file using the EZlib component. If
* input and output file names are not specified then it is assumed that
* the file names are contained in a provided ini file.
*/
void CEZlibEZipTests::DoEZlibGZipDeflateL()
{
//Open input file
_LIT(KInputFile, "c:\\private\\E80000B7\\zip\\input\\Ezlib.doc");
TFileName inputFile(KInputFile);
RFile input;
err = input.Open(iRfs, inputFile, EFileStream | EFileRead | EFileShareExclusive);
if(err != KErrNone)
{
INFO_PRINTF1(KOpenFileError);
User::Leave(err);
}
CleanupClosePushL(input);
//open output file
_LIT(KOutputFile, "c:\\private\\E80000B7\\zip\\input\\Ezlib.gz");
TFileName outputFile(KOutputFile);
RFile output;
err = output.Replace(iRfs, OutputFile, EFileStream | EFileWrite | EFileShareExclusive);
if(err != KErrNone)
{
INFO_PRINTF1(KCreateFileError);
User::Leave(err);
}
CleanupClosePushL(output);
CEZFileToGZip *compressor = CEZFileToGZip::NewLC(iRfs, iOutputFileLocation, iInputFile);
while(compressor->DeflateL())
{
}
CleanupStack::PopAndDestroy(2);
}
Decompressing a file contained in the GZip format can be performed by
passing the GZip file and the input file name to the constructor of the
CEZGZipToFile
class. The client then calls the
InflateL()
function repeatedly until the decompression is
complete.
/*
* Decompresses the file contained in a GZip file using the EZlib component. If
* input and output file names are not specified then it is assumed that
* the file names are contained in a provided ini file.
*/
void CEZlibEZipTests::DoEZlibGZipInflateL()
{
//open output file
_LIT(KOutputFile, "c:\\private\\E80000B7\\zip\\input\\Ezlib.doc");
TFileName outputFile(KOutputFile);
RFile output;
err = output.Replace(iRfs, OutputFile, EFileStream | EFileWrite | EFileShareExclusive);
if(err != KErrNone)
{
INFO_PRINTF1(KCreateFileError);
User::Leave(err);
}
CleanupClosePushL(output);
CEZGZipToFile *decompressor = CEZGZipToFile::NewLC(iRfs, iInputFileLocation, iOutputFile);
while(decompressor->InflateL())
{
}
CleanupStack::PopAndDestroy(2);
}
The decompression of a file archive involves the input file being
passed to the constructor of the CZipFile
class. Note that
the CZipFile
is a read only interface and hence does not
support compression of files to a zip archive. Furthermore, it does not support
multiple zip file archives.
The input archive file is opened to get the properties of all the files
in the archive. Each member of the zip archive is accessed through the
CZipFileMemberIterator
iterator class. This class provides
functions to point to the first file in the archive and to move through all the
entries in the archive. Once a member file is accessible, its properties can be
retrieved by the CZipFileMember
class.
The extracted files from the archive is stored in the output folder. If the output folder is not available a new folder is created before the archive is decompressed. The following example code illustrates the decompression of file archive .
/*
* Decompresses all the files in a Zip Archive using the EZlib
* component. If an input filename is not specified it is assumed that the
* input file name is contained in a provided ini file.
*/
void CEZlibEZipTests::DoEZlibZipArchiveDecompressL()
{
TInt err = KErrNone;
HBufC8 *outputBuffer = HBufC8::NewLC(outputBufferSize);
_LIT(KInputFile, "c:\\private\\E80000B7\\zip\\input\\EzlibArchive.zip");
TFileName inputFile(KInputFile);
RFile input;
err = input.Open(iRfs, inputFile, EFileStream | EFileRead | EFileShareExclusive);
if(err != KErrNone)
{
INFO_PRINTF1(KOpenFileError);
User::Leave(err);
}
CleanupClosePushL(input);
CZipFile *zipFile = CZipFile::NewL(iRfs, input);
CleanupStack::PushL(zipFile);
CZipFileMemberIterator *fileMemberIter = zipFile->GetMembersL();
// iZipArchiveEzlibFolder = GenerateZipArchiveFolderNameL(aInputFileName);
// iZipArchiveEzlibFolder.Append(KZipArchiveEzlib);
for(TOLDEZIP::CZipFileMember *fileMember = fileMemberIter->NextL(); fileMember != NULL; fileMember = fileMemberIter->NextL())
{
TFileName tmpfilename(*(fileMember->Name()));
// Check if we have a folder or file
TPtrC lastChar = tmpfilename.Right(1);
if(lastChar.Compare(_L("\\")) != 0 && lastChar.Compare(_L("/")) != 0)
{
//
RFile output;
err = output.Replace(iRfs, tmpfilename, EFileStream | EFileWrite | EFileShareExclusive);
if(err != KErrNone)
{
INFO_PRINTF1(KCreateFileError);
User::Leave(err);
}
CleanupClosePushL(output);
TOLDEZIP::RZipFileMemberReaderStream *readerStream;
zipFile->GetInputStreamL(fileMember, readerStream);
CleanupStack::PushL(readerStream);
TPtr8 pOutputBuffer = outputBuffer->Des();
do
{
err = readerStream->Read(pOutputBuffer, outputBufferSize);
output.Write(pOutputBuffer);
} while(err == KErrNone);
if(err != KErrEof)
{
User::Leave(err);
}
CleanupStack::PopAndDestroy(2);
}
else
{
TFileName fullPath("c:\\private\\E80000B7\\zip\\input\\");
fullPath.Append(tmpfilename);
iRfs.MkDir(fullPath);
}
}
CleanupStack::PopAndDestroy(3);
}