VB.NET Examples
This page has a few example code snips showing how to use DotNetZip from VB.NET.
There are full working examples shipped in the DotNetZip "developers' kit" download. They are packaged as Visual Studio projects, and can be compiled and run from within Visual Studio or using the .NET SDK (with msbuild). Get the DotNetZip devkit on
the downloads pageSee also, the Full ASP.NET Examples
in C#, or
in VB.NET.
Create a Zip archive, add files to it, save it. This is the basic programming model for the ZipFile object. Key points of interest, the
Using clause is important. The ZipFile object implements the IDisposable interface, indicating that users of the object need to call Dispose() on it when finished using it. The
Using clause guarantees that the Dispose() method is called implicitly. This will close the file pointer and allow you to move the resulting zip file, rename it, delete it, whatever. If you do not call Dispose(), the generated zip file won't be available to use elsewhere, possibly until your application
exits. Normally, you would surround the code that uses DotNetZip in a Try...Catch, which is not shown here.
Using zip As ZipFile = New ZipFile()
zip.AddFile("c:\photos\personal\7440-N49th.png")
zip.AddFile("c:\Desktop\2008_Annual_Report.pdf")
zip.AddFile("ReadMe.txt")
zip.Save("MyZipFile.zip")
End Using
Unpack or extract items from a zip file. This is probably the 2nd most common thing people do with DotNetZip. Again, note the
Using clause. Very important. The key method demonstrated here is the ZipEntry.Extract. The first parameter is the Directory to which to extract. Specifying True as the value of the 2nd parameter tells the Extract() method to overwrite any existing file by that name. Be careful with that!
Private Sub MyExtract
Dim ZipToUnpack As String = "C1P3SML.zip"
Dim UnpackDirectory As String = "Extracted Files"
Using zip1 As ZipFile = ZipFile.Read(ZipToUnpack)
Dim e As ZipEntry
' here, we extract every entry, but we could extract conditionally,
' based on entry name, size, date, checkbox status, etc.
For Each e In zip1
e.Extract(UnpackDirectory, ExtractExistingFileAction.OverwriteSilently)
Next
End Using
End Sub
Create a Zip archive that uses passwords and encryption to protect the files. This is the same as the first example, but we've added password protection into the mix. We create a new ZipFile instance, and then add a few files into it, specifying different passwords for different items. The passwords are implicitly applied to the entries added to the ZipFile. Upon extraction in WinZip, Windows Explorer, or some other tool, the user will have to specify the appropriate passwords to extract the given files. Keep in mind that using password protection in Zip files does not protect the
list of files contained in the Zip archive, nor the details of those files, like filename, size, date, and so on. Finally, once again notice the ever-present
Using clause.
Using zip As New ZipFile()
'the first entry is not protected by a password
zip.AddFile("c:\datafiles\ReadMe.txt", "")
'the next entry is protected by a password
zip.Password = "123456!"
zip.AddFile("c:\photos\personal\7440-N49th.png", "images")
'the next two entries are protected by a different password
zip.Password= "!Secret1"
zip.AddFile("c:\Documents\2005_Annual_Report.pdf", "files\documents")
zip.AddFile("c:\Documents\PerformanceAnalysis.docx", "files\documents")
' the final entry added to the archive does not use a password
zip.Password= Nothing
zip.AddFile("c:\Boilerplate\Disclaimer.doc", "files\documents")
zip.Save("Protected.zip")
End Using
Create a Zip archive that uses WinZip-compatible AES encryption. Answering concerns that the standard password protection supported by all zip tools is weak, WinZip has extended the ZIP specification and added a way to use AES Encryption to protect entries in the Zip file. Unlike the "PKZIP encryption" specified in the PKZIP spec, AES Encryption (
http://en.wikipedia.org/wiki/Advanced_Encryption_Standard) is a general encryption standard, usable to encrypt any sort of data, not just zip entries. Along with being general, it is also a much stronger encryption algorithm that the PKZIP approach - harder to crack without the password. And, AES can use variable key sizes, to vary the strength even more. WinZip supports 128-bit and 256-bit AES Encryption. DotNetZip supports the same file format as WinZip, therefore, creating a zip file that employs WinZip AES encryption using DotNetZip will result in zip archive that is readable by WinZip. It all sounds very complicated but it is very easy to use with DotNetZip - all the details are taken care of. Keep in mind though, that Zip archives that use WinZip-compatible AES encryption may not be extractable using tools other than WinZip. For example, Windows Explorer cannot unpack a "compressed folder" that uses AES encryption. But, if you
really want your ZipEntries to be private, you should use AES encryption.
Using zip As New ZipFile
zip.Password = "Sensor1 Secret!" ' do not forget this!
zip.Encryption = EncryptionAlgorithm.WinZipAes256
zip.AddFile("c:\datafiles\RawData-2009-02-12.csv", "")
zip.Save("Data-AES-Encrypted.zip")
End Using
Create a Zip archive that uses WinZip-compatible AES encryption. An alternative to the above. This version sets the Encryption and Password properties on the ZipEntry itself, rather than on the ZipFile. This allows control over the Password and Encryption used for each entry, when multiple entries are added to a zip archive.
Using zip As New ZipFile
Dim e1 as ZipEntry
e1 = zip.AddFile("c:\datafiles\RawData-2009-02-12.csv", "")
e1.Password = "Sensor1 Secret!" ' do not forget this!
e1.Encryption = EncryptionAlgorithm.WinZipAes256
zip.Save("Data-AES-Encrypted.zip")
End Using
Create a Zip archive that uses ZIP64 extensions. Designed many years ago, the original zip specification from PKWARE allowed for 32-bit quantities for the compressed and uncompressed sizes of zip entries, as well as a 32-bit quantity for specifying the length of the zip archive itself, and a maximum of 65535 entries. These limits are now regularly exceeded in many backup and archival scenarios. If you have a file larger than about 4.2gb, you will run into this limit. Recently, PKWare added extensions to the original zip spec, called "ZIP64 extensions", to raise those limitations. Just as with AES Encryption, not all zip tools can read ZIP64 archives (though that will change rapidly); because of this, the use of these extensions is optional and explicit in DotNetZip. This example shows how to use the UseZip64WhenSaving property to govern whether the ZipFile instance will use the ZIP64 extensions when writing zip archives within a call to one of the Save() methods.
Using zip As New ZipFile
zip.UseZip64WhenSaving = Zip64Option.AsNecessary
zip.AddFile("c:\datafiles\RawData-2009-02-12.csv", "")
zip.Save("Data-backup.zip")
End Using
Create and save a zip file, with progress events that update a WinForms progressbar. This is basically a very simple method that zips up a named directory. The complexity comes in when handling the progress events for the save. This example shows the application handling three different flavors of save progress that the library reports: progress for a single entry, progress for the archive, and save completion. Progress for the single entry is reported with every chunk of data that is compressed. If you have a 1gb file, it's useful to get a progress update, as the compression may take 10 seconds or more. Progress for the archive is reported after every entry has been compressed and written to the zip archive. If you have 2000 entries, it's nice to get a progress update. With those two flavors of report, you can update 2 progress bars: one for entry progress and one for archive progress. The final flavor of save progress event is "Save completed." You know what that means. Here's the code.
Private Sub DoSave(ByVal p As Object)
Dim options As WorkerOptions = TryCast(p, WorkerOptions)
Try
Using zip1 As ZipFile = New ZipFile
zip1.AddDirectory(options.Folder)
Me._entriesToZip = zip1.EntryFileNames.Count
Me.SetProgressBars()
AddHandler zip1.SaveProgress, _
New EventHandler(Of SaveProgressEventArgs)(AddressOf Me.zip1_SaveProgress)
zip1.Save(options.ZipName)
End Using
Catch exc1 As Exception
MessageBox.Show(String.Format("Exception while zipping: {0}", exc1.Message))
Me.btnCancel_Click(Nothing, Nothing)
End Try
End Sub
Private Sub zip1_SaveProgress(ByVal sender As Object, ByVal e As SaveProgressEventArgs)
Select Case e.EventType
Case ZipProgressEventType.Saving_AfterWriteEntry
Me.StepArchiveProgress(e)
Exit Select
Case ZipProgressEventType.Saving_Completed
Me.SaveCompleted()
Exit Select
Case ZipProgressEventType.Saving_EntryBytesRead
Me.StepEntryProgress(e)
Exit Select
End Select
If Me._saveCanceled Then
e.Cancel = True
End If
End Sub
Private Sub StepArchiveProgress(ByVal e As SaveProgressEventArgs)
If Me.progressBar1.InvokeRequired Then
Me.progressBar1.Invoke(New SaveEntryProgress(AddressOf Me.StepArchiveProgress), New Object() {e})
ElseIf Not Me._saveCanceled Then
Me._nFilesCompleted += 1
Me.progressBar1.PerformStep()
Me._totalBytesAfterCompress = (Me._totalBytesAfterCompress + e.CurrentEntry.CompressedSize)
Me._totalBytesBeforeCompress = (Me._totalBytesBeforeCompress + e.CurrentEntry.UncompressedSize)
' progressBar2 is the one dealing with the item being added to the archive
' if we got this event, then the add of that item (or file) is complete, so we
' update the progressBar2 appropriately.
Me.progressBar2.Value = Me.progressBar2.Maximum = 1
MyBase.Update()
End If
End Sub
Private Sub SaveCompleted()
If Me.lblStatus.InvokeRequired Then
Me.lblStatus.Invoke(New MethodInvoker(AddressOf SaveCompleted))
'Me.lblStatus.Invoke(New MethodInvoker(Me, DirectCast(Me.SaveCompleted, IntPtr)))
Else
Me.lblStatus.Text = String.Format("Done, Compressed {0} files, {1:N0}% of original", _
Me._nFilesCompleted, _
((100 * Me._totalBytesAfterCompress) / _
CDbl(Me._totalBytesBeforeCompress)))
Me.ResetState()
End If
End Sub
Private Sub StepEntryProgress(ByVal e As SaveProgressEventArgs)
If Me.progressBar2.InvokeRequired Then
Me.progressBar2.Invoke(New SaveEntryProgress(AddressOf Me.StepEntryProgress), New Object() {e})
ElseIf Not Me._saveCanceled Then
If (Me.progressBar2.Maximum = 1) Then
Dim entryMax As Long = e.TotalBytesToTransfer
Dim absoluteMax As Long = &H7FFFFFFF
Me._progress2MaxFactor = 0
Do While (entryMax > absoluteMax)
entryMax = (entryMax / 2)
Me._progress2MaxFactor += 1
Loop
If (CInt(entryMax) < 0) Then
entryMax = (entryMax * -1)
End If
Me.progressBar2.Maximum = CInt(entryMax)
Me.lblStatus.Text = String.Format("{0} of {1} files...({2})", _
(Me._nFilesCompleted + 1), _
Me._entriesToZip, e.CurrentEntry.FileName)
End If
Dim xferred As Integer = CInt((e.BytesTransferred >> Me._progress2MaxFactor))
Me.progressBar2.Value = IIf((xferred >= Me.progressBar2.Maximum), _
Me.progressBar2.Maximum, _
xferred)
MyBase.Update()
End If
End Sub
Extract with a Progress event. Extract entries from the zip file, using a progress event. This is helpful in tracking the progress of an extraction, which can take a long time for very large files, or when zip archives have many entries.
Private Shared justHadByteUpdate As Boolean = False
Private Shared Sub MyExtractProgress(ByVal sender As Object, ByVal e As ExtractProgressEventArgs)
If (e.EventType Is ZipProgressEventType.Extracting_EntryBytesWritten) Then
If ExtractTest.justHadByteUpdate Then
Console.SetCursorPosition(0, Console.CursorTop)
End If
Console.Write(" {0}/{1} ({2:N0}%)", e.BytesWritten, e.TotalBytesToWrite, (CDbl(e.BytesWritten) / (0.01 * e.TotalBytesToWrite)))
ExtractTest.justHadByteUpdate = True
ElseIf (e.EventType Is ZipProgressEventType.Extracting_BeforeExtractEntry) Then
If ExtractTest.justHadByteUpdate Then
Console.WriteLine
End If
Console.WriteLine("Extracting: {0}", e.NameOfLatestEntry)
ExtractTest.justHadByteUpdate = False
End If
End Sub
Private Sub MyExtract
Dim Overwrite as ExtractExistingFileAction = ExtractExistingFileAction.OverwriteSilently
Dim ZipToUnpack As String = "C1P3SML.zip"
Dim UnpackDirectory As String = "Extracted Files"
StatusMessage.Text = String.Format("Extracting file {0} to {1}", ZipToUnpack, UnpackDirectory )
Using zip1 As ZipFile = ZipFile.Read(ZipToUnpack)
AddHandler zip1.ExtractProgress, AddressOf MyExtractProgress
Dim e As ZipEntry
' here, we extract every entry, but we could extract conditionally,
' based on entry name, size, date, checkbox status, etc.
For Each e In zip1
e.Extract(UnpackDirectory, Overwrite)
Next
End Using
End Sub
Create a zip file, add a file, and also add an entry from a string. You can add files and directories to archives, but you can also create entries in archives from in-memory things, like a String, or a stream. This example shows how to create a zip archive and add a "file entry" into the archive, without actually referring to an on-disk file.
Dim Content As String = "This string will be the content of the Readme.txt file in the zip archive."
Using zip1 As ZipFile = New ZipFile
zip1.AddEntry("Readme.txt", "", Content)
zip1.AddFile("MyDocuments\Resume.doc", "files")
zip1.Comment = ("This zip file was created at " & DateTime.Now.ToString("G"))
zip1.Save("Content.zip")
End Using
Create a split zip containing all the files in a folder. This will produce multiple files in output, each limited to 2mb in size. The files will be named Projext.z01, Projext.z02, Projext.z03, ... Projext.zip. The resulting zip file can be opened by WinZip, PKZip, DotNetZip, or any tool or library that supports split or "spanned" zips.
Using zip As New ZipFile()
'' add all those files to the ProjectX folder in the zip file
zip.AddDirectory("c:\my Documents\ProjectX", "ProjectX")
zip.Comment = "This zip was created at " & System.DateTime.Now.ToString("G")
zip.MaxOutputSegmentSize = 2*1024*1024 '' 2mb
zip.Save("ProjextX.zip")
End Using
Read in a zip file, remove a few entries, save the file. This shows the third usage pattern for DotNetZip. The first is creating a zip file. The second is extracting archives. The third is editing an existing zip file. In this example we will remove a few entries from an existing zip file. We look at the entries and mark them for removal, then later we actually remove them from the ZipFile. The reason this is done in two passes is that an item in a collection cannot be removed from the collection while the collection itself is being enumerated. This is enforced at runtime, no way around it. So we enumerate the collection of entries in the ZipFile with the first
For Each e In Zip below. This uses the "implicit" collection of entries (of type ZipEntry) that is exposed by ZipFile. We cannot call RemoveEntry() here, because we are within an enumeration. Each entry that needs to be removed from the ZipFile gets added to a
separate collection. Then we end the enumeration of the collection of Entries with (
Next). In pass 2, we do
another enumeration, but this one is on the MarkedEntries collection. Again, it is an enumeration, so we
cannot remove entries from the MarkedEntries collection within the scope of that enumeration, but we
can remove those entries from a different collection, in this case from the collection of ZipEntry objects held by the ZipFile instance.
Dim Threshold As New DateTime(2007, 7, 4)
Using zip As ZipFile = ZipFile.Read("PackedDocuments.zip")
' We cannot remove the entry from the list, within the context of
' an enumeration of said list.
' So we add the doomed entry to a list to be removed later.
' pass 1: mark the entries for removal
Dim MarkedEntries As New System.Collections.Generic.List(Of ZipEntry)
Dim e As ZipEntry
For Each e In zip
' here, we apply the criterion to remove the entry. It is a time-based criterion, but you could
' use anything you like. Extension of the file, size of the entry, etc etc.
If (e.LastModified < Threshold) Then
MarkedEntries.Add(e)
End If
Next
' pass 2: actually remove the entry.
Dim zombie As ZipEntry
For Each zombie In MarkedEntries
zip.RemoveEntry(zombie)
Next
zip.Comment = "This archive has been updated."
zip.Save
End Using
Read a zipfile and extract its contents to the current working directory. Set the StatusMessageTextWriter so that verbose messages are generated to Console.Out. Unless you write a ton of Console/Command Line programs, this status writer won't be interesting to you. But you can use the same approach with a WinForms app, passing in a StringWriter of your own to collect status messages.
Using zip As ZipFile.Read(FilePath)
zip.StatusMessageTextWriter= System.Console.Out
'Status Messages will be sent to the console during extraction
zip.ExtractAll()
End Using
Create a ZipFile, add a bunch of items, whether files or directories. This example shows how to re-map the directory structure in the zip file you create. You can add files to a zip file, but the directory structure in the zip file need not exactly match the directory structure of the files on disk. Using the "DirectoryInArchive parameter to the AddItem() method, you can specify the directory in the archive for the added entries. The directory structure in the zip file will be used upon extraction to the end-user's disk.
Dim itempaths As String() = _
New String() { "c:\temp\Readme.txt", _
"MyProposal.docx", _
"SupportingFiles", _
"images\Image1.jpg" }
Try
Using zip As New ZipFile
Dim i As Integer
For i = 1 To itempaths.Length - 1
' will add Files or Dirs, recursing and flattening subdirectories.
zip.AddItem(itempaths(i), "flat")
Next i
zip.Save(ZipToCreate)
End Using
Catch ex1 As Exception
Console.Error.WriteLine("exception: {0}", ex1.ToString())
End Try
Create a self-extracting archive. DotNetZip supports the generation of self-extracting archives, also known as SFX files. All the ZipFile usage is the same as it is when creating a "Regular" zip file; the only thing different is the Save method you must call SaveSelfExtractor() instead of Save(). There are two flavors of self-extractor: one runs on the command line, and the other pops up a Windows GUI to guide the user through the extraction. As of v1.8 of DotNetZip, the SFX archive is also a zip file, and so the .exe should be readable by any zip tool, as a zip file.
Dim DirectoryPath As String = "c:\Documents\Project7"
Using zip As New ZipFile
zip.AddDirectory(DirectoryPath, System.IO.Path.GetFileName(DirectoryPath))
zip.Comment = "This will be embedded into a self-extracting console-based exe"
zip.SaveSelfExtractor("archive.exe", SelfExtractorFlavor.ConsoleApplication)
End Using
Update some entries in a Zip file. Sometimes you want to open an existing zip archive and modify one or more of the entries. For example, you may want to refresh those entries with updated content from the disk. The UpdateFile() and UpdateDirectory() methods allow you to do that. This example shows how to use UpdateFile().
Using zip1 As New ZipFile
' the UpdateFile method works even if the entry does not yet exist.
' Really it should be called "AddOrUpdateFile"
zip1.UpdateFile("MyDocuments\Readme.txt", "")
zip1.UpdateFile("CustomerList.csv", "")
zip1.Comment = "This zip archive has been created."
zip1.Save("Content.zip")
End Using
'...do stuff here...
Using zip2 As ZipFile = ZipFile.Read("Content.zip")
zip2.UpdateFile("Updates\Readme.txt", "")
zip2.Comment = "This zip archive has been updated: the Readme has been changed."
zip2.Save
End Using
Create a zip file within a zip file. This example saves an "inner zip file" to a MemoryStream, and then embeds it in an outer zip file.
Public Sub Run()
Using s1 As Stream = ZipIntoMemory("c:\temp\dir1")
Using s2 As Stream = ZipIntoMemory("c:\temp\dir2")
Using zip1 as New ZipFile
zip1.AddEntry("test1.zip", "", s1)
zip1.AddEntry("test2.zip", "", s2)
' save to a file. Could also save to a stream here
zip1.Save("Tescher.zip")
End Using
End Using
End Using
End Sub
Public Function ZipIntoMemory(ByVal path As String) As Stream
Dim ms As New MemoryStream
Using zip1 as New ZipFile
zip1.AddDirectory(path, "Result")
zip1.Save(ms)
End Using
' move the stream position to the beginning
ms.Seek(0,SeekOrigin.Begin)
Return ms
End Function
DotNetZip with LINQ
You can query entries in the zip file via LINQ, or use LINQ to select files to be added to the zip.
See the examples.
Other Examples
Quick Unzip WinForms application.