ZIP Tutorial
Back to tutorial list...
Table of content
# Namespaces and assemblies
To use the features of Rebex ZIP for .NET described here, you have to reference
the Rebex.Zip.dll assembly in your project.
It contains the ZipArchive and other classes in Rebex.IO.Compression namespace.
In your source files, import the following namespace:
C#
using Rebex.IO.Compression;
VB.NET
Imports Rebex.IO.Compression
back to top...
# Simple API - static methods
The ZipArchive class provides a set of static methods.
These can be used to achieve simple actions:
Compression
C#
// add content of the local directory C:\Data\
// to the directory \Data-2010 (within the ZIP archive)
// (ZIP archive C:\archive.zip doesn't have to exist)
ZipArchive.Add(@"C:\archive.zip", @"C:\Data\*", @"\Data-2010");
// add all *.TXT files from the local directory C:\Data\
// to the directory \Data-2010 (within the ZIP file)
// (ZIP archive C:\archive.zip doesn't have to exist)
ZipArchive.Add(@"C:\archive.zip", @"C:\Data\*.txt", @"\Data-2010");
// add all *.TXT files from the local directory C:\Data\
// to the root of the ZIP file overwriting all already existing files
// (ZIP archive C:\archive.zip doesn't have to exist)
ZipArchive.Add(
@"C:\archive.zip",
@"C:\Data\*.txt",
@"\",
ArchiveTraversalMode.NonRecursive,
ArchiveActionOnExistingFile.OverwriteAll);
VB.NET
' add content of the local directory C:\Data\
' to the directory \Data-2010 (within the ZIP archive)
' (ZIP archive C:\archive.zip doesn't have to exist)
ZipArchive.Add("C:\archive.zip", "C:\Data\*", "\Data-2010")
' add all *.TXT files from the local directory C:\Data\
' to the directory \Data-2010 (within the Zip file)
' (ZIP archive C:\archive.zip doesn't have to exist)
ZipArchive.Add("C:\archive.zip", "C:\Data\*.txt", "\Data-2010")
' add all *.TXT files from the local directory C:\Data\
' to the root of the Zip file overwriting all already existing files
' (ZIP archive C:\archive.zip doesn't have to exist)
ZipArchive.Add( _
"C:\archive.zip", _
"C:\Data\*.txt", _
"/", _
ArchiveTraversalMode.NonRecursive, _
ArchiveActionOnExistingFile.OverwriteAll)
Decompression
C#
// extract whole content of the ZIP archive to the existing local directory C:\Data
ZipArchive.ExtractAll(@"C:\archive.zip", @"C:\Data");
// extract whole content of the directory \Data-2010 (within the ZIP file)
// to the existing local directory C:\Data
ZipArchive.Extract(@"C:\archive.zip", @"\Data-2010\*", @"C:\Data");
// extract all *.TXT files from the directory \Data-2010 (within the ZIP file)
// to the existing local directory C:\Data
ZipArchive.Extract(@"C:\archive.zip", @"\Data-2010\*.html", @"C:\Data");
VB.NET
' extract whole content of the ZIP archive to the existing local directory C:\Data
ZipArchive.ExtractAll("C:\archive.zip", "C:\Data")
' extract whole content of the directory \Data-2010 (within the ZIP file)
' to the existing local directory C:\Data
ZipArchive.Extract("C:\archive.zip", "\Data-2010\*", "C:\Data")
' extract all *.TXT files from the directory \Data-2010 (within the ZIP file)
' to the existing local directory C:\Data
ZipArchive.Extract("C:\archive.zip", "\Data-2010\*.html", "C:\Data")
Deleting
C#
// deletes all *.TXT files from the root of the ZIP archive
ZipArchive.Delete(@"C:\archive.zip", "*.txt", ArchiveTraversalMode.NonRecursive);
// deletes directory \Data-2009 with all of its content
ZipArchive.Delete(@"C:\archive.zip", @"\Data-2009", ArchiveTraversalMode.Recursive);
VB.NET
' deletes all *.TXT files from the root of the ZIP archive
ZipArchive.Delete("C:\archive.zip", "*.txt", ArchiveTraversalMode.NonRecursive)
' deletes directory \Data-2009 with all of its content
ZipArchive.Delete("C:\archive.zip", "\Data-2009", ArchiveTraversalMode.Recursive)
If you need more features than those offered by the simple static methods (such as
retrieving a list of files in a ZIP archive or displaying a progress bar) you
will have to open a ZIP archive by creating a new instance of the ZipArchive class.
back to top...
# ZIP basics - opening and closing a ZIP archive
To open a ZIP archive, simply create a new instance of of the ZipArchive class.
Then use its methods to perform the desired actions.
When you are done with the ZIP archive, call
ZipArchive object's Close method to close the underlying
file (and save pending changes if required). Alternatively, utilize the using
keyword.
Opening a ZIP archive
C#
// open the ZIP archive from an existing file
ZipArchive zip = new ZipArchive(@"C:\archive.zip", ArchiveOpenMode.Open);
// ... do some work
// close the archive
zip.Close(ArchiveSaveAction.Auto);
VB.NET
' open the ZIP archive from an existing file
Dim zip As New ZipArchive("C:\archive.zip", ArchiveOpenMode.Open)
' ... do some work
' close the ZIP archive
zip.Close(ArchiveSaveAction.Auto)
Listing the contents of the ZIP archive
Note the use of using keyword here.
C#
// open the ZIP archive
using (ZipArchive zip = new ZipArchive(@"C:\archive.zip"))
{
// get collection of all items in the root of the ZIP archive
ZipItemCollection items = zip.GetItems(@"\", ArchiveTraversalMode.Recursive);
// sort the collection by name (directories first)
items.Sort();
// display info about each item
foreach (ZipItem item in items)
{
if (item.IsDirectory)
Console.WriteLine("D {0} [{1}]", item.Name, item.LastWriteTime);
else
Console.WriteLine(
"f {0} {1}B [{2}]", item.Name, item.Length, item.LastWriteTime);
}
}
VB.NET
' open the ZIP archive
Using zip As New ZipArchive("C:\archive.zip")
' get collection of all items in the root of the ZIP archive
Dim items = zip.GetItems("/", ArchiveTraversalMode.Recursive)
' sort the collection by name (directories first)
items.Sort()
' display info about each item
For Each item As ZipItem In items
If item.IsDirectory Then
Console.WriteLine("D {0} [{1}]", item.Name, item.LastWriteTime)
Else
Console.WriteLine( _
"f {0} {1}B [{2}]", item.Name, item.Length, item.LastWriteTime)
End If
Next item
End Using
back to top...
# Adding files (compressing)
To add files into the ZIP archive, use Add or AddFile methods.
The AddFile method only adds a single file. This makes it possible to specify a different file name for it.
To use the original name, just specify the target directory path with an ending slash instead.
C#
// add 'C:\Data\file.txt' file to the (root of the) ZIP archive
zip.AddFile(@"C:\Data\file.txt");
// add local file to the archive directory \Data-2010
// and name the added file "file-01.txt"
zip.AddFile(@"C:\Data\file.txt", @"\Data-2010\file-01.txt");
// add local file to the \Data-2010\ archive directory
// (the ending slash in the archive path indicates that you
// actually mean a directory instead of an extension-less file name)
zip.AddFile(@"C:\Data\file.txt", @"\Data-2010\");
VB.NET
' add 'C:\Data\file.txt' file to the (root of the) ZIP archive
zip.AddFile("C:\Data\file.txt")
' add local file to the archive directory \Data-2010
' and name the added file "file-01.txt"
zip.AddFile("C:\Data\file.txt", "\Data-2010\file-01.txt")
' add local file to the \Data-2010\ archive directory
' (the ending slash in the archive path indicates that you
' actually mean a directory instead of an extension-less file name)
zip.AddFile("C:\Data\file.txt", "\Data-2010\")
The Add method adds multiple files or directories in a single call.
The first argument specifies a file, a directory or a group of files or directories (see path/mask) to add.
The second argument is the target directory path (in the ZIP archive).
Optional arguments specify various compression options like traversal mode or action on existing files.
C#
// add all; *.txt files from 'C:\Data'
// to the (root of the) ZIP archive
zip.Add(@"C:\Data\*.txt");
// add all *.txt files from 'C:\Data'
// to the '\Data-2010' directory in the ZIP archive
zip.Add(@"C:\Data\*.txt", @"\Data-2010");
// add the whole content of 'C:\Data'
// to the '\Data-2010' directory in the ZIP archive
// (overwrite all already-existing files)
zip.Add(
@"C:\Data\*",
@"\Data-2010",
ArchiveTraversalMode.Recursive,
ArchiveActionOnExistingFile.OverwriteAll);
VB.NET
' add all; *.txt files from 'C:\Data'
' to the (root of the) ZIP archive
zip.Add("C:\Data\*.txt")
' add all *.txt files from 'C:\Data'
' to the '\Data-2010' directory in the ZIP archive
zip.Add("C:\Data\*.txt", "\Data-2010")
' add the whole content of 'C:\Data'
' to the '\Data-2010' directory in the ZIP archive
' (overwrite all already-existing files)
zip.Add( _
"C:\Data\*", _
"\Data-2010", _
ArchiveTraversalMode.Recursive, _
ArchiveActionOnExistingFile.OverwriteAll)
back to top...
# Extracting files (decompressing)
To extract data from a ZIP archive, use Extract, ExtractAll or ExtractFile methods.
The ExtractFile method only extracts a single file. This makes it possible to specify a different file name for it.
To use the original name, just specify the target directory path with an ending slash instead.
C#
// extract '\Data-2010\file.txt' file to 'C:\Data\file-01.txt' file
zip.ExtractFile(@"\Data-2010\file.txt", @"C:\Data\file-01.txt");
// extract '\Data-2010\file.txt' file to 'C:\Data' directory
// (the ending slash in the archive path indicates that you
// actually mean a directory instead of an extension-less file name)
zip.ExtractFile(@"\Data-2010\file.txt", @"C:\Data\");
VB.NET
' extract '\Data-2010\file.txt' file to 'C:\Data\file-01.txt' file
zip.ExtractFile("\Data-2010\file.txt", "C:\Data\file-01.txt")
' extract '\Data-2010\file.txt' file to 'C:\Data' directory
' (the ending slash in the archive path indicates that you
' actually mean a directory instead of an extension-less file name)
zip.ExtractFile("\Data-2010\file.txt", "C:\Data\")
The Extract method extracts multiple files or directories in a single call.
The first argument specifies a file, a directory or a group of files and directories (see path/mask) to extract.
The second argument is the target directory path (in the local filesystem).
Optional arguments specify various compression options like traversal mode or action on existing files.
C#
// extract whole ZIP archive to 'C:\Data' directory
zip.ExtractAll(@"C:\Data");
// extract all *.txt files from '\Data-2010' archive directory
// to 'C:\Data' directory
zip.Extract(@"\Data-2010\*.txt", @"C:\Data");
// extract whole content of '\Data-2010' archive directory
// to 'C:\Data' directory and overwrite all already-existing files
zip.Extract(
@"\Data-2010\*",
@"C:\Data",
ArchiveTraversalMode.Recursive,
ArchiveActionOnExistingFile.OverwriteAll);
VB.NET
' extract whole ZIP archive to 'C:\Data' directory
zip.ExtractAll("C:\Data")
' extract all *.txt files from '\Data-2010' archive directory
' to 'C:\Data' directory
zip.Extract("\Data-2010\*.txt", "C:\Data")
' extract whole content of '\Data-2010' archive directory
' to 'C:\Data' directory and overwrite all already-existing files
zip.Extract( _
"\Data-2010\*", _
"C:\Data", _
ArchiveTraversalMode.Recursive, _
ArchiveActionOnExistingFile.OverwriteAll)
The ExtractAll method is a shortcut for extracting the whole content of the ZIP archive to the specified directory.
back to top...
# Traversal modes
Traversal mode is an optional argument for Add, Extract and Delete methods.
It specifies whether to include the content of subdirectories in the requested operation, and how to traverse them:
ArchiveTraversalMode
ArchiveTraversalMode.NonRecursive - Only compresses files and directories matching the specified path/mask.
The content of matched directories is not compressed.ArchiveTraversalMode.Recursive - Recursive mode. Processes all files and subdirectories matching the specified path/mask.
If the source path is a masked path, files/directories in the first level are matched and if their name
matches the specified mask, their whole content is compressed. (For example, source path
"C:\Data\text*" compresses all files and directories whose name starts with "text" - any files and subdirectories in the matched directories are also
compressed, regardless of their names).ArchiveTraversalMode.DeepMatch - Recursive xcopy-like mode. This is similar to Recursive mode, but the mask is
applied to files on all levels and all subdirectories are included in the search. (DeepMatch mode can create a lot of empty directories
if a wide directory hierarchy is specified but only contains few matching files.)
back to top...
# Deleting files and directories within the archive
To delete a file or a directory in the ZIP archive, use Delete method. Optionally, specify a traversal mode (useful when deleting a whole directory tree).
Another optional argument is a save action - this makes it possible to either rearrange (shrink) the ZIP file to remove the unused space left by the deleted files.
By default, Delete method does rearrange the ZIP file if needed (ArchiveSaveAction.Auto). An alternative is to
specify ArchiveSaveAction.None to skip rearranging (shrinking) and perform this operation later
by explicitly calling Save(ArchiveSaveAction.Shrink) method later or Close(ArchiveSaveAction.Shrink) method when closing the archive.
C#
// delete 'file.txt'
zip.Delete(@"\file.txt");
// delete whole '\Data-2009' directory with all subfiles and subdirectories
zip.Delete(@"\Data-2009", ArchiveTraversalMode.Recursive);
// delete several files without shrinking (to save time)
zip.Delete(@"\file1.txt", ArchiveSaveAction.None);
zip.Delete(@"\file2.txt", ArchiveSaveAction.None);
zip.Delete(@"\file3.txt", ArchiveSaveAction.None);
// now shrink the archive (remove any unused space)
zip.Save(ArchiveSaveAction.Shrink);
// delete whole '\Data-2009' directory with all its files and subdirectories,
// save any changes and shrink the archive - all in one call
zip.Delete(@"\Data-2009", ArchiveTraversalMode.Recursive, ArchiveSaveAction.Shrink);
VB.NET
' delete 'file.txt'
zip.Delete("\file.txt")
' delete whole '\Data-2009' directory with all subfiles and subdirectories
zip.Delete("\Data-2009", ArchiveTraversalMode.Recursive)
' delete several files without shrinking (to save time)
zip.Delete("\file1.txt", ArchiveSaveAction.None)
zip.Delete("\file2.txt", ArchiveSaveAction.None)
zip.Delete("\file3.txt", ArchiveSaveAction.None)
' now shrink the archive (remove any unused space)
zip.Save(ArchiveSaveAction.Shrink)
' delete whole '\Data-2009' directory with all its files and subdirectories,
' save any changes and shrink the archive - all in one call
zip.Delete("\Data-2009", ArchiveTraversalMode.Recursive, ArchiveSaveAction.Shrink)
back to top...
# Moving (renaming) files withing the archive
To move and rename files or directories in a ZIP archive, use ZipArchive object's Move method (rename or move) or
ZipItem object's Rename method (rename only).
C#
// get the item object for '\dir\file.txt'
ZipItem item = zip.GetItem(@"\dir\file.txt");
// rename the item (the new path will be '\dir\renamed.txt')
item.Rename("renamed.txt");
// move the '\dir\file.txt' file to '\moved' directory
zip.Move(@"\dir\file.txt", @"\moved\file.txt");
// move the "\dir\file.txt" file to '\moved' directory
// and rename it to 'renamed.txt"
zip.Move(@"\dir\file.txt", @"\moved\renamed.txt");
VB.NET
' get the item object for '\dir\file.txt'
Dim item As ZipItem = zip.GetItem("\dir\file.txt")
' rename the file (the new path will be '\dir\renamed.txt')
item.Rename("renamed.txt")
' move the '\dir\file.txt' file to '\moved' directory
zip.Move("\dir\file.txt", "\moved\file.txt")
' move the "\dir\file.txt" file to '\moved' directory
' and rename it to 'renamed.txt"
zip.Move("\dir\file.txt", "\moved\renamed.txt")
back to top...
# Listing ZIP archive contents
Each file and directory within a ZIP archive (ZipArchive class) is represented by a ZipItem object
that holds information such as name, compressed/uncompressed length, last modification date, comment, etc.
ZipItem can be retrieved by 2 methods.
GetItem method or ZipArchive indexer - returns a ZipItem object that represents
the specified file or directory (or null/Nothing if it doesn't exist).GetItems method - returns a collection of ZipItem objects matching the specified
arguments. (GetItems returns a list of files that would be extracted if the Extract method with identical arguments was called.)
C#
// get information about the '\Data-2010' directory
ZipItem info1 = zip.GetItem(@"\Data-2010");
// equivalent to the previous call (GetItem method)
ZipItem info2 = zip[@"\Data-2010"];
// get all items (files and directories) in the '\Data-2010' directory
ZipItemCollection items = zip.GetItems(@"\Data-2010", ArchiveTraversalMode.NonRecursive);
// get all items (files and directories) from the 'Data-2010' directory
// including all subdirectories
ZipItemCollection allItems = zip.GetItems(
@"\Data-2010",
ArchiveTraversalMode.Recursive);
// get all directories whose name starts with 'Data'
ZipItemCollection dataDirectories = zip.GetItems(
@"\Data*",
ArchiveTraversalMode.NonRecursive,
ArchiveItemTypes.Directories);
// get whole content of all directories whose name starts with 'Data'
ZipItemCollection dataContent = zip.GetItems(
@"\Data*",
ArchiveTraversalMode.Recursive,
ArchiveItemTypes.All);
// get all .txt files in the archive
ZipItemCollection txtFiles = zip.GetItems(
"*.txt",
ArchiveTraversalMode.DeepMatch,
ArchiveItemTypes.Files);
VB.NET
' get information about the '\Data-2010' directory
Dim info1 = zip.GetItem("\Data-2010")
' equivalent to the previous call (GetItem method)
Dim info2 = zip("\Data-2010")
' get all items (files and directories) in the '\Data-2010' directory
Dim items = zip.GetItems("\Data-2010", ArchiveTraversalMode.NonRecursive)
' get all items (files and directories) from the '\Data-2010' directory
' including all subdirectories
Dim allItems As ZipItemCollection = zip.GetItems( _
"\Data-2010", _
ArchiveTraversalMode.Recursive)
' get all directories whose name starts with 'Data'
Dim dataDirectories As ZipItemCollection = zip.GetItems( _
"\Data*", _
ArchiveTraversalMode.NonRecursive, _
ArchiveItemTypes.Directories)
' get whole content of all directories whose name starts with 'Data'
Dim dataContent As ZipItemCollection = zip.GetItems( _
"\Data*", _
ArchiveTraversalMode.Recursive, _
ArchiveItemTypes.Directories)
' get all .txt files in the archive
Dim txtFiles As ZipItemCollection = zip.GetItems( _
"*.txt", _
ArchiveTraversalMode.Recursive, _
ArchiveItemTypes.Files)
back to top...
# Protecting ZIP with password
To encrypt files, simply set the Password property of the ZipArchive class first.
From the moment you set the Password newly added files are encrypted until you unset the Password.
Unset means assign a null reference (Nothing in Visual Basic) to the Password property.
Note that setting the Password property to an empty string causes the files to be encrypted with the empty password.
To use other than default encryption algorithm, use the EncryptionAlgorithm property of the ZipArchive class.
Please note that we also support Zip 2.0 (traditional PKWARE encryption) to enable compatibility with old legacy applications,
but this algorithm is considered weak by today's standards.
C#
// create new ZIP archive
using (ZipArchive zip = new ZipArchive(@"C:\archive.zip", ArchiveOpenMode.Create))
{
// set the Password first
zip.Password = "PASSword#123";
// optionally change the default Encryption algorithm
zip.EncryptionAlgorithm = EncryptionAlgorithm.Aes128;
// now add files
zip.Add(@"C:\Data");
}
VB.NET
' create new ZIP archive
Using zip As New ZipArchive("C:\archive.zip", ArchiveOpenMode.Create)
' set the Password first
zip.Password = "PASSword#123"
' optionally change the default Encryption algorithm
zip.EncryptionAlgorithm = EncryptionAlgorithm.Aes128
' now add files
zip.Add("C:\Data")
End Using
Decryption process is very similar, but you can choose from two ways. Either set the Password property of the ZipArchive class
or register the PasswordRequired event. The event is fired when you are trying to extract encrypted file, but you didn't specify a password
or when the specified password is invalid.
C#
// open a ZIP archive
using (ZipArchive zip = new ZipArchive(@"C:\archive.zip", ArchiveOpenMode.Open))
{
// set the Password first
zip.Password = "PASSword#123";
// extract whole ZIP content
zip.ExtractAll(@"C:\Data");
}
VB.NET
' open a ZIP archive
Using zip As New ZipArchive("C:\archive.zip", ArchiveOpenMode.Open)
' set the Password first
zip.Password = "PASSword#123"
' extract whole ZIP content
zip.ExtractAll("C:\Data")
End Using
Real scenario decryption process using PasswordRequired event is shown in the ZIP Extractor sample.
C#
// open a ZIP archive
using (ZipArchive zip = new ZipArchive(@"C:\archive.zip", ArchiveOpenMode.Open))
{
// set the PasswordRequired event first
zip.PasswordRequired +=
new EventHandler<ZipPasswordRequiredEventArgs>(zip_PasswordRequired);
// extract whole ZIP content
zip.ExtractAll(@"C:\Data");
}
// ...
// handler for the PasswordRequired event
void zip_PasswordRequired(object sender, ZipPasswordRequiredEventArgs e)
{
// get the password from user
string password = GetUserPassword();
// set the Password or Cancel whole operation
if (password == null)
e.Action = ArchivePasswordActions.Cancel;
else
e.Password = password;
}
VB.NET
' open a ZIP archive
Using zip As New ZipArchive("C:\archive.zip", ArchiveOpenMode.Open)
' set the PasswordRequired event first
AddHandler zip.PasswordRequired, AddressOf zip_PasswordRequired
' extract whole ZIP content
zip.ExtractAll("C:\Data")
End Using
' ...
' handler for the PasswordRequired event
Public Sub zip_PasswordRequired( _
ByVal sender As Object, _
ByVal e As ZipPasswordRequiredEventArgs)
' get the password from user
Dim password = GetUserPassword()
' set the Password or Cancel whole operation
If password Is Nothing Then
e.Action = ArchivePasswordActions.Cancel
Else
e.Password = password
End If
End Sub
back to top...
# Progress info and progress event
To get informed about the progress of the current compress/decompress operations, just register the ProgressChanged event.
When using multi-file operations like Add, Extract or ExtractAll methods,
the ProgressChanged event handler will receive useful information: currently processed file, its length, total progress, number of bytes processed, etc.
When only processing a single file using AddFile or ExtractFile method, the ProgressChanged event handler
will still receive a subset of the above-mentioned information (like CurrentFileProcessedPercentage).
C#
// register the Progress event
zip.ProgressChanged +=
new EventHandler<ZipProgressChangedEventArgs>(zip_ProgressChanged);
// extract all files, this will fire the Progress event
zip.ExtractAll(@"C:\Data");
// ...
// handler for the Progress event
void zip_ProgressChanged(object sender, ZipProgressChangedEventArgs e)
{
switch (e.OperationStep)
{
// display info about currently compressing/extracting file
case ArchiveOperationStep.FileProcessing:
if (e.Operation == ArchiveOperation.Add)
Console.WriteLine(
"Compressing file '{0}' to '{1}' {2}B [{3}/{4}] ...",
e.ExternalItemPath,
e.ArchiveItemPath,
e.CurrentFileLength,
e.FilesProcessed + 1,
e.FilesTotal);
else
Console.WriteLine(
"Extracting file '{0}' to '{1}' {2}B [{3}/{4}]...",
e.ArchiveItemPath,
e.ExternalItemPath,
e.CurrentFileLength,
e.FilesProcessed + 1,
e.FilesTotal);
break;
// display progress of curently compressing/extracting file
// and progress of the whole operation
case ArchiveOperationStep.FileDataBlockProcessed:
Console.WriteLine(
"{0} [{2}% / {3}%]",
Path.GetFileName(e.ExternalItemPath),
e.CurrentFileProgressPercentage,
e.ProgressPercentage);
break;
}
}
VB.NET
' register the Progress event
AddHandler zip.ProgressChanged, AddressOf zip_ProgressChanged
' extract all files, this will fire the Progress event
zip.ExtractAll("C:\Data")
' ...
' handler for the Progress event
Public Sub zip_ProgressChanged( _
ByVal sender As Object, _
ByVal e As ZipProgressChangedEventArgs)
Select Case e.OperationStep
Case ArchiveOperationStep.FileProcessing
' display info about currently compressing/extracting file
If e.Operation = ArchiveOperation.Add Then
Console.WriteLine( _
"Compressing file '{0}' to '{1}' {2}B [{3}/{4}] ...", _
e.ExternalItemPath, _
e.ArchiveItemPath, _
e.CurrentFileLength, _
e.FilesProcessed + 1, _
e.FilesTotal)
Else
Console.WriteLine( _
"Extracting file '{0}' to '{1}' {2}B [{3}/{4}]...", _
e.ArchiveItemPath, _
e.ExternalItemPath, _
e.CurrentFileLength, _
e.FilesProcessed + 1, _
e.FilesTotal)
End If
Case ArchiveOperationStep.FileDataBlockProcessed
' display progress of curently compressing/extracting file
' and progress of the whole operation
Console.WriteLine( _
"{0} [{2}% / {3}%]", _
Path.GetFileName(e.ExternalItemPath), _
e.CurrentFileProgressPercentage, _
e.ProgressPercentage)
End Select
End Sub
back to top...
# Handling multi-file operation problems
With multi-file operations, things can occasionally go wrong due to unforeseen problems.
To be informed about such problems, just register the ProblemDetected event.
When things go wrong (e.g. a file we are trying to extract already exists in the target folder), the the ProblemDetected event
is raised and it can be used to specify the desired action to take.
The type of the problem is determined using the event-argument's ProblemType property. This describes what is going on.
Exception property contains further information - it's actually an exception that would be thrown unless a different action
is choosen. Use IsActionPossible method (or PossibleActions flag property) to determine which actions are possible,
and specify the desired action using the Action property.
C#
// register the ProblemDetected event
zip.ProblemDetected +=
new EventHandler<ZipProblemDetectedEventArgs>(zip_ProblemDetected);
// extract all files, this will fire the ProblemDetected event if any problem occurs
zip.ExtractAll(@"C:\Data");
// ...
// handler for the ProblemDetected event
void zip_ProblemDetected(object sender, ZipProblemDetectedEventArgs e)
{
switch (e.ProblemType)
{
// overwrite already existing files and inform the user
case ArchiveProblemType.FileExists:
if (e.IsActionPossible(ArchiveProblemActions.Overwrite))
{
if (e.Operation == ArchiveOperation.Add)
Console.WriteLine(
"Overwriting file {0} with {1}...",
e.ArchiveItemPath,
e.ExternalItemPath);
else
Console.WriteLine(
"Overwriting file {0} with {1}...",
e.ExternalItemPath,
e.ArchiveItemPath);
e.Action = ArchiveProblemActions.Overwrite;
}
break;
// if CRC check faild while extracting a file, delete unusable local file,
// inform the user and continue in batch processing
// by skipping this corrupted file
case ArchiveProblemType.CrcCheckFailed:
Console.WriteLine(
"CRC check faild. Deleting local file {0}...",
e.ExternalItemPath);
File.Delete(e.ExternalItemPath);
e.Action = ArchiveProblemActions.Skip;
break;
}
}
VB.NET
' register the Progress event
AddHandler zip.ProblemDetected, AddressOf zip_ProblemDetected
' extract all files, this will fire the ProblemDetected event if any problem occurs
zip.ExtractAll("C:\Data")
' ...
' handler for the ProblemDetected event
Public Sub zip_ProblemDetected( _
ByVal sender As Object, _
ByVal e As ZipProblemDetectedEventArgs)
Select Case e.ProblemType
' overwrite already existing files and inform the user
Case ArchiveProblemType.FileExists
If e.IsActionPossible(ArchiveProblemActions.Overwrite) Then
If e.Operation = ArchiveOperation.Add Then
Console.WriteLine( _
"Overwriting file {0} with {1}...", _
e.ArchiveItemPath, _
e.ExternalItemPath)
Else
Console.WriteLine( _
"Overwriting file {0} with {1}...", _
e.ExternalItemPath, _
e.ArchiveItemPath)
End If
e.Action = ArchiveProblemActions.Overwrite
End If
' if CRC check failed while extracting a file, delete unusable local file,
' inform the user and continue in batch processing
' by skipping this corrupted file
Case ArchiveProblemType.CrcCheckFailed
Console.WriteLine( _
"CRC check faild. Deleting local file {0}...", _
e.ExternalItemPath)
File.Delete(e.ExternalItemPath)
e.Action = ArchiveProblemActions.Skip
End Select
End Sub
back to top...
# Compression level
When compressing data, you can choose between compression speed and quality using the ZipArchive object's CompressionLevel property.
Levels from 0 to 9 are supported:
- 0 = No compression, but very fast.
- 1 = The fastest compression, but the worst compression ratio.
- 6 = Default compression, a compromise between speed and compression ratio.
- 9 = Best compression ratio, but the slowest.
C#
// open a ZIP archive
using (ZipArchive zip = new ZipArchive(@"C:\archive.zip"))
{
// get files in the 'C:\Data' directory
string[] files = Directory.GetFiles(@"C:\Data");
// choose compression level for each file according to the file type
foreach (string file in files)
{
switch (Path.GetExtension(file))
{
// don't waste time with already-compressed files
case ".jpg":
case ".gif":
case ".mp3":
zip.CompressionLevel = 0;
zip.AddFile(file);
break;
// use best compression for all other files
default:
zip.CompressionLevel = 9;
zip.AddFile(file);
break;
}
}
}
VB.NET
' open a ZIP archive
Using zip As New ZipArchive("C:\archive.zip")
' get files in the 'C:\Data' directory
Dim files = Directory.GetFiles("C:\Data")
' choose compression level for each file according to the file type
For Each File As String In files
Select Case Path.GetExtension(File)
' don't waste time with already-compressed files
Case ".jpg", ".gif", ".mp3"
zip.CompressionLevel = 0
zip.AddFile(File)
' use best compression for all other files
Case Else
zip.CompressionLevel = 9
zip.AddFile(File)
End Select
Next File
End Using
back to top...
# Advanced optimisation hints
The ZipArchive class exposes the ArchiveSaveMode property which is set to ArchiveSaveMode.Immediate by default.
This value causes all changes made to the ZIP archive to be saved to the underlying stream immediately.
Although this makes the ZipArchive class very easy to use, it can cause a noticeable slow-down when performing a lot of "single" operations.
For example, updating the LastWriteTime property of 1000s of files will cause the full ZIP archive central-directory-structure to be saved
1000s of times again and again as well.
To avoid this, switch the ZipArchive object to ArchiveSaveMode.Delayed mode, perform the "single" operations and explicitly
call the Save method to save all changes once.
In a similar fashion, Delete method called with ArchiveSaveAction.Auto argument rearranges (shrinks) the ZIP archive
in ArchiveSaveMode.Immediate mode. If you need to perform many single Delete operations, switching to ArchiveSaveMode.Delayed mode
temporarily might result in a great speed boost.
C#
// open a ZIP archive
using (ZipArchive zip = new ZipArchive(@"C:\archive.zip"))
{
// turn off "immediately saving mode"
zip.SaveMode = ArchiveSaveMode.Delayed;
// get files in the 'C:\Data' directory
string[] files = Directory.GetFiles(@"C:\Data");
foreach (string file in files)
{
string filename = Path.GetFileName(file);
zip.AddFile(file, filename);
// set comment and last write time for the newly-added file
zip[filename].Comment = "Comment for file " + filename;
zip[filename].LastWriteTime = DateTime.Now;
}
// save all changes (comments and write times) made earlier
// (this needs to be called before turning on auto-save again)
zip.Save();
// turn on 'auto-save' mode
zip.SaveMode = ArchiveSaveMode.Immediate;
// ... do some work with ZIP archive in "immediately saving mode"
}
VB.NET
' open a ZIP archive
Using zip As New ZipArchive("C:\archive.zip")
' turn off "immediately saving mode"
zip.SaveMode = ArchiveSaveMode.Delayed
' get files in the 'C:\Data' directory
Dim files = Directory.GetFiles("C:\Data")
For Each file As String In files
Dim filename As String = Path.GetFileName(file)
zip.AddFile(file, filename)
' set comment and last write time for the newly-added file
zip(filename).Comment = "Comment for file " + filename
zip(filename).LastWriteTime = DateTime.Now
Next file
' save all changes (comments and write times) made earlier
' (this needs to be called before turning on auto-save again)
zip.Save()
'turn on 'auto-save' mode
zip.SaveMode = ArchiveSaveMode.Immediate
' ... do some work with ZIP archive in "immediately saving mode"
End Using
back to top...
# Used expressions
- Mask, masked path or path/mask is a path which contains wildcards ('*' or '?'). The wildcards are only allowed at the last level of the path
("C:\Data\*.txt" is a valid path mask, "C:\Data\*\bin" is not).
- Multi-file operations are methods which process (compress, decompress or delete) more files in a single call.
back to top...
Back to tutorial list...