// Removes specified files from zip void ZipFile::Remove(String* FileSpec, Boolean RecurseSubdirectories) { ZipFile* tempZipFile; OpenFileForUnzip(); // Just wrapping in a try/catch/finally to make sure temp zip file gets removed try { Regex* filePattern = GetFilePatternRegularExpression(FileSpec, caseSensitive); IEnumerator* filesEnum = files->GetEnumerator(); CompressedFile* file; // Create temporary zip file to hold remove results tempZipFile = CreateTempZipFile(); // Loop through compressed file collection while (filesEnum->MoveNext()) { file = static_cast<CompressedFile*>(filesEnum->Current); // We copy all files into destination zip file except those user requested to be removed... if (!filePattern->IsMatch(GetSearchFileName(FileSpec, file->get_FileName(), RecurseSubdirectories))) CopyFileInZip(file, this, tempZipFile, S"Remove Zip File"); } // Now make the temp file the new zip file Close(); tempZipFile->Close(); File::Delete(fileName); File::Move(tempZipFile->fileName, fileName); } catch (CompressionException* ex) { // We just rethrow any errors back to user throw ex; } catch (Exception* ex) { throw ex; } __finally { // If everything went well, temp zip will no longer exist, but just in case we tidy up and delete the temp file... DeleteTempZipFile(tempZipFile); } // We'll reload the file list after remove if requested... if (autoRefresh) Refresh(); }
// Extracts specified files from zip void ZipFile::Extract(String* FileSpec, String* DestPath, UpdateOption OverwriteWhen, Boolean RecurseSubdirectories, PathInclusion CreatePathMethod) { // Any file spec in destination path will be ignored DestPath = JustPath(DestPath); char* pszPassword = NULL; char* pszFileName = NULL; OpenFileForUnzip(); // Just wrapping in a try/catch/finally to make sure unmanaged code allocations always get released try { Regex* filePattern = GetFilePatternRegularExpression(FileSpec, caseSensitive); IEnumerator* filesEnum = files->GetEnumerator(); CompressedFile* file; String* sourceFileName; String* destFileName; bool writeFile; int err; // Get ANSI password, if one was provided if (password) if (password->get_Length()) pszPassword = StringToCharBuffer(password); // Loop through compressed file collection while (filesEnum->MoveNext()) { file = static_cast<CompressedFile*>(filesEnum->Current); sourceFileName = file->get_FileName(); if (filePattern->IsMatch(GetSearchFileName(FileSpec, sourceFileName, RecurseSubdirectories))) { pszFileName = StringToCharBuffer(sourceFileName); err = unzLocateFile(hUnzipFile, pszFileName, (caseSensitive ? 1 : 2)); free(pszFileName); pszFileName = NULL; // We should find file in zip file if it was in our compressed file collection if (err != Z_OK) throw new CompressionException(String::Concat(S"Extract Zip File Error: Compressed file \"", sourceFileName, "\" cannot be found in zip file!")); // Open compressed file for unzipping if (pszPassword) err = unzOpenCurrentFilePassword(hUnzipFile, pszPassword); else err = unzOpenCurrentFile(hUnzipFile); if (err != Z_OK) throw new CompressionException(S"Extract Zip File", err); // Get full destination file name switch (CreatePathMethod) { case PathInclusion::FullPath: destFileName = sourceFileName; break; case PathInclusion::NoPath: destFileName = String::Concat(DestPath, Path::GetFileName(sourceFileName)); break; case PathInclusion::RelativePath: destFileName = String::Concat(DestPath, sourceFileName); break; } // Make sure destination directory exists Directory::CreateDirectory(JustPath(destFileName)); // See if destination file already exists if (File::Exists(destFileName)) { DateTime lastUpdate = File::GetLastWriteTime(destFileName); switch (OverwriteWhen) { case UpdateOption::Never: writeFile = false; break; case UpdateOption::Always: writeFile = true; break; case UpdateOption::ZipFileIsNewer: writeFile = (DateTime::Compare(file->get_FileDateTime(), lastUpdate) > 0); break; case UpdateOption::DiskFileIsNewer: writeFile = (DateTime::Compare(file->get_FileDateTime(), lastUpdate) < 0); break; default: writeFile = false; break; } } else writeFile = true; if (writeFile) { System::Byte buffer[] = new System::Byte[BufferSize]; System::Byte __pin * destBuff = &buffer[0]; // pin buffer so it can be safely passed into unmanaged code... FileStream* fileStream = File::Create(destFileName); int read; __int64 total = 0, len = -1; // Send initial progress event len = file->get_UncompressedSize(); CurrentFile(destFileName, sourceFileName); FileProgress(0, len); // Read initial buffer read = unzReadCurrentFile(hUnzipFile, destBuff, buffer->get_Length()); if (read < 0) throw new CompressionException(S"Extract Zip File", read); while (read) { // Write data to file stream, fileStream->Write(buffer, 0, read); // Raise progress event total += read; FileProgress(total, len); // Read next buffer from source file stream read = unzReadCurrentFile(hUnzipFile, destBuff, buffer->get_Length()); if (read < 0) throw new CompressionException(S"Extract Zip File", read); } fileStream->Close(); } // Close compressed file unzCloseCurrentFile(hUnzipFile); } } } catch (CompressionException* ex) { // We just rethrow any errors back to user throw ex; } catch (Exception* ex) { throw ex; } __finally { if (pszPassword) free(pszPassword); if (pszFileName) free(pszFileName); } }