ZipFile Manual

About

The ZipFile class provides means to work with ZIP archives. ZIP files can be created, modified and extracted.

Note
To create ZIP archives with the MAXON API see Archives Manual.

Allocation/Deallocation

ZipFile objects are created with the usual tools, see Entity Creation and Destruction Manual (Classic).

Opening and Closing

Filename

Metadata

Compression Level

CRC

Extracting an Entire Archive

// This example demonstrates extracting the selected ZIP file to a given folder.
Filename fnZip, fnDest;
if (!fnZip.FileSelect(FILESELECTTYPE::ANYTHING, FILESELECT::LOAD, "Choose a ZIP file to extract..."_s, "zip"_s))
return maxon::OK;
if (!fnDest.FileSelect(FILESELECTTYPE::ANYTHING, FILESELECT::DIRECTORY, "Choose a directory to extract to..."_s))
return maxon::OK;
if (zf == nullptr)
return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
if (!zf->ExtractToDirectory(fnZip, fnDest))
return maxon::UnknownError(MAXON_SOURCE_LOCATION);

Current File

Internally the ZipFile class has a pointer to the "current" file inside of the archive. The following functions provide means to change the current file pointer to another file or directory.

// This example iterates the files in ZIP archive and finds the first C4D scene (if any).
Bool sceneFound = false;
UInt32 fileSizeUncompressed = 0;
if (!zf->GoToFirstFile())
return PrintMsgAndCloseZipFile(zf, "Error: No files in ZIP archive."); // small custom helper function
do
{
// Break loop, as soon as the first scene file is encountered.
String sName;
if (zf->GetCurrentFileInfo(zfi) && !(zfi.lFlags & ZIP_FLAG_DIRECTORY) && zf->GetCurrentFileInfo(&sName) && Filename(sName).CheckSuffix("c4d"_s))
{
fileSizeUncompressed = zfi.lUncompressedSize;
sceneFound = true;
break;
}
} while (zf->GoToNextFile());
if (!sceneFound || fileSizeUncompressed == 0)
return PrintMsgAndCloseZipFile(zf, "Error: No C4D scene found in archive."); // small custom helper function

The current file can be extracted from a ZIP archive:

// This example demonstrates looping through the files of a ZIP file and extract each of them separately.
Filename fnZip, fnDest;
if (!fnZip.FileSelect(FILESELECTTYPE::ANYTHING, FILESELECT::LOAD, "Choose a ZIP file to extract files from..."_s))
return maxon::OK;
if (!fnDest.FileSelect(FILESELECTTYPE::ANYTHING, FILESELECT::DIRECTORY, "Choose a destination directory for the extracted files..."_s))
return maxon::OK;
if (zf == nullptr)
return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
if (!zf->Open(fnZip, true)) // Open for reading.
return maxon::UnknownError(MAXON_SOURCE_LOCATION);
// Iterate files and extract one by one.
if (!zf->GoToFirstFile())
{
ApplicationOutput("No files in ZIP archive.");
zf->Close();
return maxon::OK;
}
do
{
// Extract only files (just to demonstrate, that directory structure from archive will stay intact nevertheless).
if (zf->GetCurrentFileInfo(zfi) && !(zfi.lFlags & ZIP_FLAG_DIRECTORY))
zf->ExtractCurrentFile(fnDest);
} while (zf->GoToNextFile());
ShowInFinder(fnDest, false);
zf->Close();

Comprehensive information can be retrieved for the current file:

Similar to "normal" files (e.g. BaseFile) the current file can be opened for reading:

// This example reads the current file in chunks from a ZIP archive.
// Open the file.
if (!zf->OpenCurrentFile())
return PrintMsgAndCloseZipFile(zf, "Error: Failed to open current file in archive."); // small custom helper function
// Allocate a buffer to read the file into.
maxon::AutoMem<Char> buffer = NewMemClear(Char, fileSizeUncompressed) iferr_ignore("nullptr check next");
if (buffer == nullptr)
return PrintMsgAndCloseZipFile(zf, "Error: Failed to open allocate buffer."); // small custom helper function
// Reading in chunks of 4096 (0x1000) bytes, just for demonstration purposes.
const Int32 maxChunkSize = 0x1000;
Char* bufferCurrentPos = buffer;
Char* const bufferEnd = buffer.GetPointer() + fileSizeUncompressed; // Points to the first byte behind the allocated buffer.
while (!zf->EndOfCurrentFile())
{
const Int32 chunkSize = ClampValue((Int32)(bufferEnd - bufferCurrentPos), 0, maxChunkSize);
if (chunkSize <= 0)
break;
const Int32 numBytesRead = zf->ReadCurrentFile(bufferCurrentPos, chunkSize);
if (numBytesRead < 0)
break;
bufferCurrentPos += numBytesRead;
}
if (!zf->EndOfCurrentFile() || (bufferCurrentPos != bufferEnd))
{
return PrintMsgAndCloseZipFile(zf, "Error: Something went wrong, while reading file from archive."); // small custom helper function
}
zf->Close();

Add to an ZIP File

// This example demonstrates how a ZIP file is created and files are added.
Filename fnZip;
if (!fnZip.FileSelect(FILESELECTTYPE::ANYTHING, FILESELECT::SAVE, "Save Zip File"_s))
return maxon::OK;
if (zf == nullptr)
return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
if (!zf->Open(fnZip, false, ZIP_APPEND_CREATE))
return maxon::UnknownError(MAXON_SOURCE_LOCATION);
Filename fnCopy;
while (fnCopy.FileSelect(FILESELECTTYPE::ANYTHING, FILESELECT::LOAD, "Select file to add to Zip File"_s))
{
zf->CopyInFileInZip(fnCopy, fnCopy.GetFileString());
}
zf->Close();

Further Reading

FILESELECT::DIRECTORY
@ DIRECTORY
Folder selection dialog.
ZipFile::ExtractCurrentFile
Bool ExtractCurrentFile(const Filename &fnDir, BaseThread *pThread, Int32 lFlags=0x00000001, const char *pchPassword=nullptr, Filename *pfnDest=nullptr)
FILESELECT::SAVE
@ SAVE
Save dialog.
NewMemClear
#define NewMemClear(T, cnt)
Definition: defaultallocator.h:204
ZipFile::EndOfCurrentFile
Bool EndOfCurrentFile()
UInt32
maxon::UInt32 UInt32
Definition: ge_sys_math.h:61
ZipFile::CopyInFileInZip
Bool CopyInFileInZip(const Filename &fn, const String &str, const char *pchPassword=nullptr)
ZipFileInfo::lUncompressedSize
UInt32 lUncompressedSize
Uncompressed size.
Definition: lib_zipfile.h:81
Filename
Manages file and path names.
Definition: c4d_file.h:93
maxon::OK
return OK
Definition: apibase.h:2546
FILESELECTTYPE::ANYTHING
@ ANYTHING
Any file.
ZipFileInfo::lFlags
UInt32 lFlags
Flags: ZIP_FLAG.
Definition: lib_zipfile.h:76
MAXON_SOURCE_LOCATION
#define MAXON_SOURCE_LOCATION
Definition: memoryallocationbase.h:66
ZipFile::ReadCurrentFile
Int32 ReadCurrentFile(void *pBuffer, UInt32 lBufferSize)
ZipFile::ExtractToDirectory
Bool ExtractToDirectory(const Filename &fnZip, const Filename &fnDir, Int32 lFlags=0x00000001, ExtractDirectoryCallback fn=nullptr, void *pData=nullptr, const char *pChPassword=nullptr)
ZipFile::Close
Bool Close()
String
Definition: c4d_string.h:38
ZIP_FLAG_DIRECTORY
#define ZIP_FLAG_DIRECTORY
Directory flag.
Definition: lib_zipfile.h:21
iferr_ignore
#define iferr_ignore(...)
Definition: resultbase.h:1430
ZipFile::GoToFirstFile
Bool GoToFirstFile()
ZipFile::GetCurrentFileInfo
Bool GetCurrentFileInfo(ZipFileInfo &i)
ZipFile::OpenCurrentFile
Bool OpenCurrentFile(const char *pChPassword=nullptr)
ZipFile::CloseCurrentFile
Bool CloseCurrentFile()
ZipFileInfo
Definition: lib_zipfile.h:72
Filename::GetFileString
String GetFileString(void) const
ShowInFinder
Bool ShowInFinder(const Filename &fn, Bool open)
maxon::BaseRef::GetPointer
T * GetPointer()
Definition: baseref.h:82
Int32
maxon::Int32 Int32
Definition: ge_sys_math.h:60
ApplicationOutput
#define ApplicationOutput(formatString,...)
Definition: debugdiagnostics.h:208
ZIP_APPEND_CREATE
#define ZIP_APPEND_CREATE
Creates a new ZIP file.
Definition: lib_zipfile.h:132
ZipFile::GoToNextFile
Bool GoToNextFile()
ZipFile::Open
Bool Open(const Filename &fn, const Bool bRead, const Int32 lAppend=0)
FILESELECT::LOAD
@ LOAD
Load dialog.
AutoAlloc
Definition: ge_autoptr.h:36
Bool
maxon::Bool Bool
Definition: ge_sys_math.h:55
ClampValue
X ClampValue(X value, X lowerLimit, X upperLimit)
Clips a value against a lower and upper limit. The new value is returned.
Definition: apibasemath.h:221
maxon::BaseRef
Definition: apibase.h:1527
Char
maxon::Char Char
Definition: ge_sys_math.h:56
Filename::FileSelect
Bool FileSelect(FILESELECTTYPE type, FILESELECT flags, const maxon::String &title, const maxon::String &force_suffix=maxon::String())