FastZip

Neil McNeight edited this page Apr 29, 2016 · 13 revisions

This page shows how to create and extract zip files using the FastZip class.

How to create a Zip File

FastZip fastZip = new FastZip();

bool recurse = true;  // Include all files by recursing through the directory structure
string filter = null; // Dont filter any files at all
fastZip.CreateZip("fileName.zip", @"C:\SourceDirectory", recurse, filter);

Using the fileFilter parameter

If the file filter is not a null string, it is interpreted as a list of one or more regular expressions which is tested against each file name.

For example, a fileFilter value of 'txt' would match with 'Test.txt' but would also match with 'SometxtFile.doc'. To match with '.txt' you would need to add a a dot, but even then a filter of ".txt" would be interpreted as [any-character]txt. You need to add an escape character "\" before the dot to specify it as a literal match. Note that if your literal string does not have an @ sign in front of it, you will need to use two consecutive \. For example "\\.txt" or @"\.txt" are the same (and "\.txt" will not compile).

Note that "\.txt" would still match a file such as "file.txtold" or "file.txt.old", so you can append the $ specifier which matches with the end of the string: e.g "\.txt$" to ensure you only match files with the last extension as .txt

FastZip fastZip = new FastZip();

bool recurse = true;  // Include all files by recursing through the directory structure
string filter = @"\.txt$"; // Only files ending in ".txt"
fastZip.CreateZip("fileName.zip", @"C:\SourceDirectory", recurse, filter);

The file filter and folder filter are actually lists.

Multiple regular expressions are separated with a semicolon (";"). Each one can be an inclusion or exclusion. Exclusions start with a minus sign ("-").
Inclusions may start with an optional plus sign ("+"). Some examples :

// Only files ending in ".txt" or ".log" ... except for any matching "NotThisFile"
string fileFilter = @"\.txt$;\.log$;-NotThisFile";

// Only files ending in ".txt" ... except for any matching "NotThisFile" or "Today"
string fileFilter = @"\.txt$;-NotThisFile;-Today";

Matching is not case-sensitive.

Each item in your filter is matched against the entire filename including drive and full folder path. Do not start an entry with a caret ("^") unless matching the full path string. To match a complete filename (within a folder), use a folder separator (a backslash). Because the backslash is also the escape character it must be entered twice.

// Matches a file called LogFile.txt but not SomeOtherLogFile.txt
string fileFilter = @"\\LogFile.txt$";

// Same as above but without the @ sign
string fileFilter = "\\\\LogFile.txt$";

Create a zip with FastZip using progress events

You can set events which will fire on each file. This gives you the opportunity to display a progress notification, and to decide whether to stop.

using System;
using System.IO;
using ICSharpCode.SharpZipLib.Core;
using ICSharpCode.SharpZipLib.Zip;

private int _uptoFileCount;
private int _totalFileCount;

public void TestFastZipCreate(string backupFolderPath) {

        _totalFileCount = FolderContentsCount(backupFolderPath);

        FastZipEvents events = new FastZipEvents();
        events.ProcessFile = ProcessFileMethod;
        FastZip fastZip = new FastZip(events);

        fastZip.CreateEmptyDirectories = true;

        string zipFileName = Directory.GetParent(backupFolderPath).FullName + "\\ZipTest.zip";

        fastZip.CreateZip(zipFileName, backupFolderPath, true, "");
    }

    private void ProcessFileMethod(object sender, ScanEventArgs args) {
        _uptoFileCount ++;
        int percentCompleted = _uptoFileCount * 100 / _totalFileCount;
        // do something here with a progress bar
        // file counts are easier as sizes take more work to calculate, and compression levels vary by file type

        string fileName = args.Name;
        // To terminate the process, set args.ContinueRunning = false
        if (fileName == "stop on this file")
            args.ContinueRunning = false;
    }

    // Returns the number of files in this and all subdirectories
    private int FolderContentsCount(string path) {
        int result = Directory.GetFiles(path).Length;
        string[ ] subFolders = Directory.GetDirectories(path);
        foreach (string subFolder in subFolders) {
            result += FolderContentsCount(subFolder);
        }
        return result;
    }

How to extract a Zip File using FastZip

C\

    using System;
    using ICSharpCode.SharpZipLib.Zip;

    public void TestFastZipUnpack(string zipFileName, string targetDir) {

        FastZip fastZip = new FastZip();
        string fileFilter = null;

        // Will always overwrite if target filenames already exist
        fastZip.ExtractZip(zipFileName, targetDir, fileFilter);
    }

VB

    Imports ICSharpCode.SharpZipLib.Zip

    Public Sub TestFastZipUnpack(ByVal zipFileName As String, ByVal targetDir As String)

        Dim fastZip As FastZip = New FastZip()
        Dim fileFilter As String = Nothing

        fastZip.ExtractZip(zipFileName, targetDir, fileFilter)
    End Sub

How to extract a Zip File using FastZip with Name Filter and Confirm Overwrite

C\

using System;
using System.Windows.Forms;
using ICSharpCode.SharpZipLib.Core;
using ICSharpCode.SharpZipLib.Zip;

private bool _stop;

public void TestFastZipUnpack(string zipFileName, string targetDir) {
    // Set the method that will be called on each file before extraction but after the OverwritePrompt (if applicable)
    FastZipEvents events = new FastZipEvents();
    events.ProcessFile = ProcessFileMethod;
    FastZip fastZip = new FastZip(events);

    // To conditionally extract files in FastZip, use the fileFilter and directoryFilter arguments.
    // The filter is a list of regex values separated with semi-colon. An entry starting with - is an exclusion.
    // See the NameFilter class for more details.
    // The following expression includes all name ending in '.dat' with the exception of 'dummy.dat'
    string fileFilter = @"+\.dat$;-^dummy\.dat$";
    string directoryFilter = null;
    bool restoreDateTime = true;

    // Will prompt to overwrite if target filenames already exist
    fastZip.ExtractZip(zipFileName, targetDir, FastZip.Overwrite.Prompt, OverwritePrompt,
                       fileFilter, directoryFilter, restoreDateTime);
}

private bool OverwritePrompt(string fileName) {
    // In this method you can choose whether to overwrite a file.
    DialogResult dr = MessageBox.Show("Overwrite " + fileName, "Overwrite?", MessageBoxButtons.YesNoCancel);
    if (dr == DialogResult.Cancel) {
        _stop = true;
        // Must return true if we want to abort processing, so that the ProcessFileMethod will be called.
        // When the ProcessFileMethod sets ContinueRunning false, processing will immediately stop.
        return true;
    }
    return dr == DialogResult.Yes;
}

private void ProcessFileMethod(object sender, ScanEventArgs args) {

    string fileName = args.Name;
    // To stop all further processing, set args.ContinueRunning = false
    if (_stop) {
        args.ContinueRunning = false;
    }
}

VB

Imports ICSharpCode.SharpZipLib.Zip
Imports ICSharpCode.SharpZipLib.Core
Imports System.Windows.Forms

Dim _stop As Boolean

Public Sub TestFastZipUnpack(ByVal zipFileName As String, ByVal targetDir As String)

    Dim events As FastZipEvents = New FastZipEvents()
    events.ProcessFile = AddressOf ProcessFileMethod
    Dim fastZip As FastZip = New FastZip(events)

    ' The only way to conditionally extraxt files in FastZip is to use the fileFilter and directoryFilter arguments.
    ' The filter is a list of regex values separated with semi-colon. An entry starting with - is an exclusion.
    ' See the NameFilter class for more examples.
    ' The following expression includes all name ending in '.dat' with the exception of 'dummy.dat'
    Dim fileFilter As String = "+\.dat$;-^dummy\.dat$"
    Dim directoryFilter As String = Nothing
    Dim restoreDateTime As Boolean = True

    ' Will prompt to overwrite if target filenames already exist
    fastZip.ExtractZip(zipFileName, targetDir, fastZip.Overwrite.Prompt, AddressOf OverwritePrompt, _
                       fileFilter, directoryFilter, restoreDateTime)
End Sub

Private Function OverwritePrompt(ByVal fileName As String) As Boolean

    ' In this method you can choose whether to overwrite a file.
    Dim dr As DialogResult = MessageBox.Show("Overwrite " + fileName, "Overwrite?", MessageBoxButtons.YesNoCancel)
    If (dr = DialogResult.Cancel) Then
        _stop = True
        ' Must return true if we want to abort processing, so that the ProcessFileMethod will be called.
        ' When the ProcessFileMethod sets ContinueRunning false, processing will immediately stop.
        Return True
    End If
    Return dr = DialogResult.Yes
End Function

Private Sub ProcessFileMethod(ByVal sender As Object, ByVal args As ScanEventArgs)

    Dim fileName As String = args.Name
    ' To stop all further processing, set args.ContinueRunning = false
    If (_stop) Then
        args.ContinueRunning = False
    End If

End Sub