85

What is an example (simple code) of how to zip a folder in C#?


Update:

I do not see namespace ICSharpCode. I downloaded ICSharpCode.SharpZipLib.dll but I do not know where to copy that DLL file. What do I need to do to see this namespace?

And do you have link for that MSDN example for compress folder, because I read all MSDN but I couldn't find anything.


OK, but I need next information.

Where should I copy ICSharpCode.SharpZipLib.dll to see that namespace in Visual Studio?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131

10 Answers10

158

This answer changes with .NET 4.5. Creating a zip file becomes incredibly easy. No third-party libraries will be required.

string startPath = @"c:\example\start";
string zipPath = @"c:\example\result.zip";
string extractPath = @"c:\example\extract";

ZipFile.CreateFromDirectory(startPath, zipPath);
ZipFile.ExtractToDirectory(zipPath, extractPath);
Jarrett Meyer
  • 19,333
  • 6
  • 58
  • 52
  • 42
    This works great. Don't forget to add a reference to System.IO.Compression.FileSystem and a using statement for System.IO.Compression. – Scott Nov 20 '15 at 17:47
  • 2
    I cannot believe how simple this is. Thank you so much! – Tom May 04 '18 at 10:56
  • 1
    I have an error when using the original path and destination path are the same, so remember to use the destination path different to the original path. – ThanhLD Feb 19 '19 at 03:17
  • @ThanhLD Yeah they didn't make it so you can put the `result.zip` inside the folder (i.e. `startPath`) unfortunately.. – JohnB Oct 23 '19 at 15:33
56

From the DotNetZip help file, http://dotnetzip.codeplex.com/releases/

using (ZipFile zip = new ZipFile())
{
   zip.UseUnicodeAsNecessary= true;  // utf-8
   zip.AddDirectory(@"MyDocuments\ProjectX");
   zip.Comment = "This zip was created at " + System.DateTime.Now.ToString("G") ; 
   zip.Save(pathToSaveZipFile);
}
shriek
  • 5,157
  • 2
  • 36
  • 42
Simon
  • 33,714
  • 21
  • 133
  • 202
22

There's nothing in the BCL to do this for you, but there are two great libraries for .NET which do support the functionality.

I've used both and can say that the two are very complete and have well-designed APIs, so it's mainly a matter of personal preference.

I'm not sure whether they explicitly support adding Folders rather than just individual files to zip files, but it should be quite easy to create something that recursively iterated over a directory and its sub-directories using the DirectoryInfo and FileInfo classes.

Noldorin
  • 144,213
  • 56
  • 264
  • 302
  • 2
    DotNetZip supports adding a Directory to a zip file, via the ZipFile.AddDirectory() methods. It recurses through the directory. – Cheeso May 26 '09 at 01:17
  • You can add a folder using SharpZipLib simply by adding the folder name plus a slash (can't recall if it's forward or backward) to the zip entry name. – devios1 Feb 01 '11 at 17:27
  • SharpZipLib has GPL license: http://weblogs.asp.net/jgalloway/archive/2007/10/25/creating-zip-archives-in-net-without-an-external-library-like-sharpziplib.aspx – JohnB Jul 07 '11 at 05:46
  • 1
    +1 for DotNetZip. The organisation I work for uses it extensively and it's great for all sorts of tasks. – Jamie Keeling Jul 27 '12 at 14:07
18

In .NET 4.5 the ZipFile.CreateFromDirectory(startPath, zipPath); method does not cover a scenario where you wish to zip a number of files and sub-folders without having to put them within a folder. This is valid when you wish the unzip to put the files directly within the current folder.

This code worked for me:

public static class FileExtensions
{
    public static IEnumerable<FileSystemInfo> AllFilesAndFolders(this DirectoryInfo dir)
    {
        foreach (var f in dir.GetFiles())
            yield return f;
        foreach (var d in dir.GetDirectories())
        {
            yield return d;
            foreach (var o in AllFilesAndFolders(d))
                yield return o;
        }
    }
}

void Test()
{
    DirectoryInfo from = new DirectoryInfo(@"C:\Test");
    using (var zipToOpen = new FileStream(@"Test.zip", FileMode.Create))
    {
        using (var archive = new ZipArchive(zipToOpen, ZipArchiveMode.Create))
        {
            foreach (var file in from.AllFilesAndFolders().OfType<FileInfo>())
            {
                var relPath = file.FullName.Substring(from.FullName.Length+1);
                ZipArchiveEntry readmeEntry = archive.CreateEntryFromFile(file.FullName, relPath);
            }
        }
    }
}

Folders don't need to be "created" in the zip-archive. The second parameter "entryName" in CreateEntryFromFile should be a relative path, and when unpacking the zip-file the directories of the relative paths will be detected and created.

Bradley Grainger
  • 27,458
  • 4
  • 91
  • 108
Gil Roitto
  • 325
  • 2
  • 8
  • Thanks. This really helped me out! Not sure why it's not up voted more. I referenced your answer here: http://stackoverflow.com/questions/36872218/using-net-ziparchive-to-zip-entire-directories-as-well-as-extra-info/36893955#36893955 – Dave Apr 27 '16 at 15:12
  • @ShmilTheCat can you try to use the .CreateEntry method for the folders? See https://stackoverflow.com/questions/15133626/creating-directories-in-a-ziparchive-c-sharp-net-4-5 – Gil Roitto Dec 11 '18 at 12:09
6

There is a ZipPackage class in the System.IO.Packaging namespace which is built into .NET 3, 3.5, and 4.0.

http://msdn.microsoft.com/en-us/library/system.io.packaging.zippackage.aspx

Here is an example how to use it. http://www.codeproject.com/KB/files/ZipUnZipTool.aspx?display=Print

dr.
  • 1,429
  • 12
  • 18
4

There's an article over on MSDN that has a sample application for zipping and unzipping files and folders purely in C#. I've been using some of the classes in that successfully for a long time. The code is released under the Microsoft Permissive License, if you need to know that sort of thing.

EDIT: Thanks to Cheeso for pointing out that I'm a bit behind the times. The MSDN example I pointed to is in fact using DotNetZip and is really very fully-featured these days. Based on my experience of a previous version of this I'd happily recommend it.

SharpZipLib is also quite a mature library and is highly rated by people, and is available under the GPL license. It really depends on your zipping needs and how you view the license terms for each of them.

Rich

Xiaofu
  • 15,523
  • 2
  • 32
  • 45
  • The example code on MSDN uses DotNetZip, a free zip library that supports compression levels and encryption (including AES encryption), though the specific sample you cited does not show that. The library produces "proper" zip files. – Cheeso May 25 '09 at 08:18
  • Thanks for mentioning that. I'm still using the original version from a few years ago which was just a stand-alone code sample, so it looks like they've done a lot more work on it. – Xiaofu May 25 '09 at 09:01
  • My apologies to Cheeso, as it looks like you are the admin if not the author of the DotNetZip library! It's proved very useful to me, even in its early form from when I first encountered it. :) – Xiaofu May 25 '09 at 09:17
  • Edited based on Cheeso's comment. – Xiaofu May 25 '09 at 09:23
2

using DotNetZip (available as nuget package):

public void Zip(string source, string destination)
{
    using (ZipFile zip = new ZipFile
    {
        CompressionLevel = CompressionLevel.BestCompression
    })
    {
        var files = Directory.GetFiles(source, "*",
            SearchOption.AllDirectories).
            Where(f => Path.GetExtension(f).
                ToLowerInvariant() != ".zip").ToArray();

        foreach (var f in files)
        {
            zip.AddFile(f, GetCleanFolderName(source, f));
        }

        var destinationFilename = destination;

        if (Directory.Exists(destination) && !destination.EndsWith(".zip"))
        {
            destinationFilename += $"\\{new DirectoryInfo(source).Name}-{DateTime.Now:yyyy-MM-dd-HH-mm-ss-ffffff}.zip";
        }

        zip.Save(destinationFilename);
    }
}

private string GetCleanFolderName(string source, string filepath)
{
    if (string.IsNullOrWhiteSpace(filepath))
    {
        return string.Empty;
    }

    var result = filepath.Substring(source.Length);

    if (result.StartsWith("\\"))
    {
        result = result.Substring(1);
    }

    result = result.Substring(0, result.Length - new FileInfo(filepath).Name.Length);

    return result;
}

Usage:

Zip(@"c:\somefolder\subfolder\source", @"c:\somefolder2\subfolder2\dest");

Or

Zip(@"c:\somefolder\subfolder\source", @"c:\somefolder2\subfolder2\dest\output.zip");
Amen Ayach
  • 4,288
  • 1
  • 23
  • 23
1

Following code uses a third-party ZIP component from Rebex:

// add content of the local directory C:\Data\  
// to the root directory in the ZIP archive
// (ZIP archive C:\archive.zip doesn't have to exist) 
Rebex.IO.Compression.ZipArchive.Add(@"C:\archive.zip", @"C:\Data\*", "");

Or if you want to add more folders without need to open and close archive multiple times:

using Rebex.IO.Compression;
...

// open the ZIP archive from an existing file 
ZipArchive zip = new ZipArchive(@"C:\archive.zip", ArchiveOpenMode.OpenOrCreate);

// add first folder
zip.Add(@"c:\first\folder\*","\first\folder");

// add second folder
zip.Add(@"c:\second\folder\*","\second\folder");

// close the archive 
zip.Close(ArchiveSaveAction.Auto);

You can download the ZIP component here.

Using a free, LGPL licensed SharpZipLib is a common alternative.

Disclaimer: I work for Rebex

Martin Vobr
  • 5,757
  • 2
  • 37
  • 43
0

"Where should I copy ICSharpCode.SharpZipLib.dll to see that namespace in Visual Studio?"

You need to add the dll file as a reference in your project. Right click on References in the Solution Explorer->Add Reference->Browse and then select the dll.

Finally you'll need to add it as a using statement in whatever files you want to use it in.

AndrewC
  • 6,680
  • 13
  • 43
  • 71
0

ComponentPro ZIP can help you achieve that task. The following code snippet compress files and dirs in a folder. You can use wilcard mask as well.

using ComponentPro.Compression;
using ComponentPro.IO;

...

// Create a new instance.
Zip zip = new Zip();
// Create a new zip file.
zip.Create("test.zip");

zip.Add(@"D:\Temp\Abc"); // Add entire D:\Temp\Abc folder to the archive.

// Add all files and subdirectories from 'c:\test' to the archive.
zip.AddFiles(@"c:\test");
// Add all files and subdirectories from 'c:\my folder' to the archive.
zip.AddFiles(@"c:\my folder", "");
// Add all files and subdirectories from 'c:\my folder' to '22' folder within the archive.
zip.AddFiles(@"c:\my folder2", "22");
// Add all .dat files from 'c:\my folder' to '22' folder within the archive.
zip.AddFiles(@"c:\my folder2", "22", "*.dat");
// Or simply use this to add all .dat files from 'c:\my folder' to '22' folder within the archive.
zip.AddFiles(@"c:\my folder2\*.dat", "22");
// Add *.dat and *.exe files from 'c:\my folder' to '22' folder within the archive.
zip.AddFiles(@"c:\my folder2\*.dat;*.exe", "22");

TransferOptions opt = new TransferOptions();
// Donot add empty directories.
opt.CreateEmptyDirectories = false;
zip.AddFiles(@"c:\abc", "/", opt);

// Close the zip file.
zip.Close();

http://www.componentpro.com/doc/zip has more examples

Alexey Semenyuk
  • 3,263
  • 2
  • 32
  • 36
  • FWIW, please see cheated.by.safabyte.net which shows Component Pro likely represents the latest incarnation of stolen software. TY – iokevins Apr 17 '20 at 17:55