Skip to content

Instantly share code, notes, and snippets.

@riordant
Created December 21, 2018 16:00
Show Gist options
  • Save riordant/0fd270560bd2101504c8b868033fc9d9 to your computer and use it in GitHub Desktop.
Save riordant/0fd270560bd2101504c8b868033fc9d9 to your computer and use it in GitHub Desktop.
Clean ZIP file creation using minizip in C++
/*
(Extension of the main answer for the question here - https://stackoverflow.com/questions/11370908/how-do-i-use-minizip-on-zlib)
* Creates a ZIP file -
after specifying an absolute path to a "root" directory, all filepaths derived from this path are stored in the ZIP file,
with only files and their paths from the root preserved.
eg. root path: /a/b/c/d/
filepaths(from root path): e/f.txt
g.dat
paths to folders (again, from a root) can be provided - in this case the method derives all sub-files and adds to "filePaths".
eg. folder path: h/i
derives files: h/i/j.exe
h/i/k.o
h/i/l/m.jpeg
Breaking up the root and derived paths allows for easy unzipping from the same directory - the layout is preserved.
*/
bool CreateZipFile (std::string rootPath, std::vector<string> folderPaths, vector<string> filePaths, std::string destinationPath)
{
zipFile zf = zipOpen(destinationPath.c_str(), APPEND_STATUS_CREATE);
if (zf == NULL)
return 1;
BOOST_FOREACH(std::string folderPath, folderPaths){
std::string fullFolderPath = rootPath + folderPath;
for (const auto & entry : boost::filesystem::directory_iterator(fullFolderPath)){
std::string fullFolderFilePath = entry.path().string();
std::string folderFilePath = fullFolderFilePath.substr(rootPath.length());
filePaths.push_back(folderFilePath);
}
}
bool failed = false;
BOOST_FOREACH(string filePath, filePaths)
{
if(failed){
break;
}
std::string fullPath = rootPath + filePath;
std::fstream file(fullPath.c_str(), std::ios::binary | std::ios::in);
if (file.is_open())
{
file.seekg(0, std::ios::end);
long size = file.tellg();
file.seekg(0, std::ios::beg);
std::vector<char> buffer(size);
if (size == 0 || file.read(&buffer[0], size)){
zip_fileinfo zfi = { 0 };
if (ZIP_OK == zipOpenNewFileInZip(zf, filePath.c_str(), &zfi, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION))
{
if (ZIP_OK != zipWriteInFileInZip(zf, size == 0 ? "" : &buffer[0], size)){
failed = true;
}
if (ZIP_OK != zipCloseFileInZip(zf)){
failed = true;
}
file.close();
continue;
}
}
file.close();
}
failed = true;
}
zipClose(zf, NULL);
if (failed){
return false;
}
return true;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment