General Information

Compression and decompression
Multi-disk archives
Password encryption and decryption
Self extract support
Exceptions
Creating and extracting archives from/in memory
Action progress notifications (callbacks)
Integrating with MSDN (Visual Studio 6.0 only)

Compression and decompression

There are some functions defined for fast operations on archive: CZipArchive::AddNewFile, CZipArchive::ExtractFile, CZipArchive::DeleteFile, CZipArchive::TestFile. You only need to call functions CZipArchive::Open - before and CZipArchive::Close - after using them. Calling CZipArchive::Close function after you've done modifying the archive is necessary for the archive to be intact.

Multi-disk archives

This library can create multi-disk archives in two ways (modes):

These two disk spanning modes create volumes with compatible internal structure. It means that you can easily convert the volumes created in one mode to the other one by renaming the files (in TDSpan mode each volume's extension (apart from the last one) consists of a 'z' letter and a number). To convert the archive from TD to PKZIP compatible archive, copy each file to the removable media, giving them the extension ".zip". You should also label each disk with the appropriate label starting from "pkback# 001" (note the space between '#' and '0').

There is a limited functions set available while working with multi-disk archives. Only adding is allowed when creating the archive and only extracting and testing after opening an existing one. Deleting files from these archives is not allowed at all.

Class CZipArchive uses write buffer to make write operations as fast as possible. You can change its size with CZipArchive::SetAdvanced function (first argument). While creating a multi-disk archive, set the size of the buffer to the maximum size of the volume for the best performance.

Popular archivers such as PKZIP and WinZip should be able to open the archive created in both modes.

Password encryption and decryption

This library supports creating and extracting the password protected archives. There are several issues you should be aware of when using this feature. To set the password for the file to be added or extracted call the function CZipArchive::SetPassword with the password as the argument. To clear the password call this function without arguments or with an empty string argument. The function has no effect on a closed archive and on the currently opened file (whether new or existing) inside archive. During opening the archive the password is cleared. You can set different passwords for different files inside the same archive, but remember to set it BEFORE opening the file. You cannot use ASCII characters with codes above 127 in the password, if you do so, the function CZipArchive::SetPassword returns false and the password is cleared. You can find out what files are password encrypted by calling CZipArchive::GetFileInfo, which fills the structure CZipFileHeader with data, and then call the method ZipFileHeader::IsEncrypted. If it returns true, the file needs a password to extract. The successful extraction of the encrypted file doesn't always mean that the password is correct. You also need to check the return value of CZipArchive::CloseFile. You could also check the size of the extracted file since it can be smaller than it should be in case of the bad password.

Self extract support

The library is capable of extracting and modifying self-extracting archives. You can create your own SFX archive as well. This is the simplest code responsible for the self-extracting:

//Windows code

int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
 CZipArchive zip;

 // get the path of the executable
 TCHAR szBuff[_MAX_PATH];
 if (!::GetModuleFileName(hInstance, szBuff, _MAX_PATH))
  return -1;

 CZipString szDest;
 // ...
 // add some code here to get the destination directory from the user 
 // for example:
 // CBrowseForFolder bf;
 //   bf.strTitle = _T("Select directory to extract files");
 //   if (!bf.GetFolder(szDest))
 //       return -1;
 //
 // class CBrowseForFolder is included in the sample application project
 // remember about including the header!
 zip.Open(szBuff, CZipArchive::zipOpenReadOnly); 
 // zipOpenReadOnly mode is necessary for self extract archives
 for (WORD i = 0; i < zip.GetCount(); i++)
  zip.ExtractFile(i, szDest);

 zip.Close();
 return 0;
 // this code will not work for the encrypted archives since it is needed
 // to get the password from the user ( a small addition to the 
 // existing code I suppose )
}

After compiling it and appending a zip archive to it (e.g. with the DOS command: copy /b SelfExtract.exe + ZipFile.zip FinalFile.exe ) you have a self extracting archive.

Exceptions

The ZipArchive library mostly uses exceptions to notify about the error occured. The library throws CZipException to notify about errors specific to the internal zip file processing. In the MFC version CZipException class is derived from CException whereas in the STL version it is derived from std::exception.

MFC version

The library throws the following exceptions inherited from CException: CMemoryException*, CFileExeption* and CZipException* (be sure to delete the object when you done with it). Handling them may be done in the following way:

try
{
 // ...
 // some operations on the ZipArchive library
}
catch (CException* e)
{
 if (e->IsKindOf( RUNTIME_CLASS( CZipException )))
 {
  CZipException* p = (CZipException*) e;
  //... and so on 
 }
 else if (e->IsKindOf( RUNTIME_CLASS( CFileException )))
 {
  CFileException* p = (CFileException*) e;
  //... and so on 
 } 
 else
 {
  // the only possibility is a memory exception I suppose
  //... and so on
 }
 e->Delete();
}

STL version

The library throws exceptions inherited from std::exception. In this case you should catch std::exception object (not a pointer to it).

Creating and extracting archives from/in memory

With the function CZipArchive::Open(CZipMemFile&, int) you can create the archive in memory and then write to disk, e.g.:

CZipArchive zip;
CZipMemFile mf;
// create archive in memory
zip.Open(mf, CZipArchive::zipCreate);
// ...
// add some files to archive here e.g. by calling CZipArchive::AddNewFile
// ...
zip.Close();
// write the archive to disk
CZipFile f;
if (f.Open("c:\\temp.zip", CZipFile::modeWrite|CZipFile::modeCreate, false)
{
 int iLen = mf.GetLength();
 BYTE* b = mf.Detach();
 f.Write(b, iLen);
 f.Close();
 // we must free the detached memory
 free(b);
}

You can as well read the archive from disk and then extract files, e.g.:

CZipFile f;
if (f.Open("c:\\temp.zip", CZipFile::modeRead, false)
{
 int iLen = f.GetLength(); 
 BYTE* b = (BYTE*)malloc((UINT)iLen);
 f.Read(b, iLen);
 f.Close();
 CZipMemFile mf;
 mf.Attach(b, iLen);
 CZipArchive zip;
 zip.Open(mf);
 // ...
 // extract files here from the archive e.g. by calling CZipArchive::ExtractFile
 // ...
 zip.Close();
}

With functions CZipArchive::AddNewFile(CZipMemFile&, LPCTSTR, int, int, unsigned long) and CZipArchive::ExtractFile(WORD, CZipMemFile&, DWORD) you can add files to archive from memory and extract them to a memory file. Now a bit larger example:

// create the archive in memory with two files inside
CZipMemFile mf;
CZipArchive zip;
zip.Open(mf, CZipArchive::zipCreate);
zip.AddNewFile("c:\\testfile1.txt");
zip.AddNewFile("c:\\testfile2.txt");
zip.Close();
//create the archive on disk and add a previously zipped file from memory
zip.Open("c:\\test.zip", CZipArchive::zipCreate);
zip.AddNewFile(mf, "File1.zip");
zip.Close();
// we have now zip-in-zip file on the disk, 
// let's extract the embedded zip file back to memory
zip.Open("c:\\test.zip");
// reset the contents of the CZipMemFile object
mf.SetLength(0);
zip.ExtractFile(0, mf);
zip.Close();
// write the file from memory to disk
CZipFile f;
if (f.Open("c:\\File1.zip", CZipFile::modeWrite|CZipFile::modeCreate, false))
{
 int iLen = mf.GetLength();
 BYTE* b = mf.Detach();
 f.Write(b, iLen);
 f.Close();
 // we must free the detached memory
 free(b);
}

One important thing: when you operate on the archive in memory, you must ensure that CZipMemory object will not be destroyed before calling CZipArchive::Close. In some cases you'll need to construct the object using the new operator, e.g.:

// ...
CZipMemFile* pmf = new CZipMemFile;
zip.Open(*pmf, CZipArchive::zipCreate);
// ...
zip.Close();
delete pmf;

Action progress notifications (callbacks)

The library has the possibility to notify about the progress of the various actions (see CZipArchive::CallbackType). To use this feature you need to define a new class derived from CZipActionCallback or from CZipSpanCallback and override CZipCallback::Callback function. Then you need to declare an object of your class and pass its address to function CZipArchive::SetCallback or CZipArchive::SetSpanCallback. Make sure that the object exists while the library performs the action the callback object was assigned to; or tell the library not to use the callback (use the same functions).

Integrating with MSDN (Visual Studio 6.0 only)

If you wish to integrate the ZipArchive help system with the MSDN library you need to:
ZipArchive Copyright © 2000 - 2006 Tadeusz Dracz . Generated at Fri Apr 7 13:55:25 2006.