ZIP Tutorial
Applies to: Rebex Total Pack, Rebex ZIP
Table of content
- Namespaces and assemblies
- Simple API - static methods
- ZIP basics - opening and closing a ZIP archive
- Adding files (compressing)
- Extracting files (decompressing)
- Traversal modes
- Deleting files and directories within the archive
- Moving (renaming) files withing the archive
- Listing ZIP archive contents
- Protecting ZIP with password
- Progress info and progress event
- Handling multi-file operation problems
- Compression level
- Advanced optimisation hints
- Used expressions
Namespaces and assemblies
To use the features of Rebex ZIP for .NET described here, you have to reference
the Rebex.Zip.dll and Rebex.Common.dll assemblies in your project.
It contains the ZipArchive
and other classes in Rebex.IO.Compression
namespace.
In your source files, import the following namespace:
using Rebex.IO.Compression;
Imports Rebex.IO.Compression
using Rebex.IO.Compression;
Imports Rebex.IO.Compression
Simple API - static methods
The ZipArchive
class provides a set of static methods.
These can be used to achieve simple actions:
Compression
// 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", @"\", TraversalMode.NonRecursive, TransferMethod.Copy, ActionOnExistingFiles.OverwriteAll);
' 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", _ "/", _ TraversalMode.NonRecursive, _ TransferMethod.Copy, _ ActionOnExistingFiles.OverwriteAll)
Decompression
// 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");
' 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
// deletes all *.TXT files from the root of the ZIP archive ZipArchive.Delete(@"C:\archive.zip", "*.txt", TraversalMode.NonRecursive); // deletes directory \Data-2009 with all of its content ZipArchive.Delete(@"C:\archive.zip", @"\Data-2009", TraversalMode.Recursive);
' deletes all *.TXT files from the root of the ZIP archive ZipArchive.Delete("C:\archive.zip", "*.txt", TraversalMode.NonRecursive) ' deletes directory \Data-2009 with all of its content ZipArchive.Delete("C:\archive.zip", "\Data-2009", TraversalMode.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.
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
// 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();
' 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()
Listing the contents of the ZIP archive
Note the use of using
keyword here.
// 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(@"\", TraversalMode.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); } }
' 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("/", TraversalMode.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
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.
// 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 // if the file already exists there and is older, overwrite it // (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\", ActionOnExistingFiles.OverwriteOlder);
' 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 ' if the file already exists there and is older, overwrite it ' (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\", ActionOnExistingFiles.OverwriteOlder)
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.
// 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", TraversalMode.Recursive, TransferMethod.Copy, ActionOnExistingFiles.OverwriteAll);
' 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", _ TraversalMode.Recursive, _ TransferMethod.Copy, _ ActionOnExistingFiles.OverwriteAll)
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.
// 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 // if the file already exists there, the file will be extracted to a renamed copy // (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\", ActionOnExistingFiles.Rename);
' 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 ' if the file already exists there, the file will be extracted to a renamed copy ' (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\", ActionOnExistingFiles.Rename)
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.
// 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", TraversalMode.Recursive, TransferMethod.Copy, ActionOnExistingFiles.OverwriteAll);
' 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", _ TraversalMode.Recursive, _ TransferMethod.Copy, _ ActionOnExistingFiles.OverwriteAll)
The ExtractAll
method is a shortcut for extracting the whole content of the ZIP archive to the
specified directory.
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 toRecursive
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.)
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.
// delete single file named 'file.txt' zip.DeleteFile(@"\file.txt"); // delete whole '\Data-2007' directory with all subfiles and subdirectories zip.Delete(@"\Data-2007", TraversalMode.Recursive); // delete several files and directories without shrinking (to save time) zip.DeleteFile(@"\file.txt", ArchiveSaveAction.None); zip.Delete(@"\*.jpg", TraversalMode.MatchFilesShallow, ArchiveSaveAction.None); zip.Delete(@"\Data-2008", TraversalMode.Recursive, 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", TraversalMode.Recursive, ArchiveSaveAction.Shrink);
' delete single file named 'file.txt' zip.DeleteFile("\file.txt") ' delete whole '\Data-2007' directory with all subfiles and subdirectories zip.Delete("\Data-2007", TraversalMode.Recursive) ' delete several files without shrinking (to save time) zip.DeleteFile("\file.txt", ArchiveSaveAction.None) zip.Delete("\*.jpg", TraversalMode.MatchFilesShallow, ArchiveSaveAction.None) zip.Delete("\Data-2008", TraversalMode.Recursive, 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", TraversalMode.Recursive, ArchiveSaveAction.Shrink)
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).
// 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");
' 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")
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 orZipArchive
indexer - returns aZipItem
object that represents the specified file or directory (or null/Nothing if it doesn't exist). -
GetItems
method - returns a collection ofZipItem
objects matching the specified arguments. (GetItems
returns a list of files that would be extracted if theExtract
method with identical arguments was called.)
// 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\*", TraversalMode.NonRecursive); // get all items (files and directories) from the 'Data-2010' directory // including all subdirectories ZipItemCollection allItems = zip.GetItems( @"\Data-2010", TraversalMode.Recursive); // get all directories whose name starts with 'Data' ZipItemCollection dataDirectories = zip.GetItems( @"\Data*", TraversalMode.NonRecursive, ArchiveItemTypes.Directories); // get whole content of all directories whose name starts with 'Data' ZipItemCollection dataContent = zip.GetItems( @"\Data*", TraversalMode.Recursive, ArchiveItemTypes.All); // get all .txt files in the archive ZipItemCollection txtFiles = zip.GetItems( "*.txt", TraversalMode.MatchFilesDeep, ArchiveItemTypes.Files);
' 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\*", TraversalMode.NonRecursive) ' get all items (files and directories) from the '\Data-2010' directory ' including all subdirectories Dim allItems As ZipItemCollection = zip.GetItems( _ "\Data-2010", _ TraversalMode.Recursive) ' get all directories whose name starts with 'Data' Dim dataDirectories As ZipItemCollection = zip.GetItems( _ "\Data*", _ TraversalMode.NonRecursive, _ ArchiveItemTypes.Directories) ' get whole content of all directories whose name starts with 'Data' Dim dataContent As ZipItemCollection = zip.GetItems( _ "\Data*", _ TraversalMode.Recursive, _ ArchiveItemTypes.All) ' get all .txt files in the archive Dim txtFiles As ZipItemCollection = zip.GetItems( _ "*.txt", _ TraversalMode.MatchFilesDeep, _ ArchiveItemTypes.Files)
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.
// 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"); }
' 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.
// 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"); }
' 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.
// 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"); } // ...
' 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 ' ...
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
).
// register the Progress event zip.ProgressChanged += new EventHandler<ZipProgressChangedEventArgs>(zip_ProgressChanged); // extract all files, this will fire the Progress event zip.ExtractAll(@"C:\Data"); // ...
' register the Progress event AddHandler zip.ProgressChanged, AddressOf zip_ProgressChanged ' extract all files, this will fire the Progress event zip.ExtractAll("C:\Data") ' ...
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 (for example 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.
// 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"); // ...
' 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") ' ...
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.
// 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; } } }
' 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
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.
// 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" }
' 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
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 tutorial list...