Skip to content

Unpack a Zip with full control over the operation

nils måsén edited this page Mar 10, 2021 · 6 revisions

Code Reference / Zip Samples / Unpack a Zip with full control over the operation

This sample illustrates many aspects:

  • skipping directory entries
  • controlling the folder where the output is placed
  • passwords
  • exception handling, closing disk files, and efficient use of memory.

While this example is purely disk files, scroll down where other inputs and outputs such as memory stream are covered.

C#

using ICSharpCode.SharpZipLib.Core;
using ICSharpCode.SharpZipLib.Zip;

public void ExtractZipFile(string archivePath, string password, string outFolder) {

    using(var fsInput = File.OpenRead(archivePath)) 
    using(var zf = new ZipFile(fsInput)){
        
        if (!String.IsNullOrEmpty(password)) {
            // AES encrypted entries are handled automatically
            zf.Password = password;
        }

        foreach (ZipEntry zipEntry in zf) {
            if (!zipEntry.IsFile) {
                // Ignore directories
                continue;
            }
            String entryFileName = zipEntry.Name;
            // to remove the folder from the entry:
            //entryFileName = Path.GetFileName(entryFileName);
            // Optionally match entrynames against a selection list here
            // to skip as desired.
            // The unpacked length is available in the zipEntry.Size property.

            // Manipulate the output filename here as desired.
            var fullZipToPath = Path.Combine(outFolder, entryFileName);
            var directoryName = Path.GetDirectoryName(fullZipToPath);
            if (directoryName.Length > 0) {
                Directory.CreateDirectory(directoryName);
            }

            // 4K is optimum
            var buffer = new byte[4096];

            // Unzip file in buffered chunks. This is just as fast as unpacking
            // to a buffer the full size of the file, but does not waste memory.
            // The "using" will close the stream even if an exception occurs.
            using(var zipStream = zf.GetInputStream(zipEntry))
            using (Stream fsOutput = File.Create(fullZipToPath)) {
                StreamUtils.Copy(zipStream, fsOutput , buffer);
            }
        }
    }
}

Visual Basic

Imports ICSharpCode.SharpZipLib.Core
Imports ICSharpCode.SharpZipLib.Zip

Public Sub ExtractZipFile(archiveFilenameIn As String, password As String, outFolder As String)
    Dim zf As ZipFile = Nothing
    Try
        Dim fs As FileStream = File.OpenRead(archiveFilenameIn)
        zf = New ZipFile(fs)
        If Not [String].IsNullOrEmpty(password) Then	' AES encrypted entries are handled automatically
            zf.Password = password
        End If
        For Each zipEntry As ZipEntry In zf
            If Not zipEntry.IsFile Then		' Ignore directories
                Continue For
            End If
            Dim entryFileName As [String] = zipEntry.Name
            ' to remove the folder from the entry:- entryFileName = Path.GetFileName(entryFileName);
            ' Optionally match entrynames against a selection list here to skip as desired.
            ' The unpacked length is available in the zipEntry.Size property.

            Dim buffer As Byte() = New Byte(4095) {}	' 4K is optimum
            Dim zipStream As Stream = zf.GetInputStream(zipEntry)

            ' Manipulate the output filename here as desired.
            Dim fullZipToPath As [String] = Path.Combine(outFolder, entryFileName)
            Dim directoryName As String = Path.GetDirectoryName(fullZipToPath)
            If directoryName.Length > 0 Then
                Directory.CreateDirectory(directoryName)
            End If

            ' Unzip file in buffered chunks. This is just as fast as unpacking to a buffer the full size
            ' of the file, but does not waste memory.
            ' The "Using" will close the stream even if an exception occurs.
            Using streamWriter As FileStream = File.Create(fullZipToPath)
                StreamUtils.Copy(zipStream, streamWriter, buffer)
            End Using
        Next
    Finally
        If zf IsNot Nothing Then
            zf.IsStreamOwner = True		' Makes close also shut the underlying stream
            ' Ensure we release resources
            zf.Close()
        End If
    End Try
End Sub