34

How can I list the contents of a zipped folder in C#? For example how to know how many items are contained within a zipped folder, and what is their name?

vbroto
  • 6,088
  • 3
  • 22
  • 12

7 Answers7

40

.NET 4.5 or newer finally has built-in capability to handle generic zip files with the System.IO.Compression.ZipArchive class (http://msdn.microsoft.com/en-us/library/system.io.compression.ziparchive%28v=vs.110%29.aspx) in assembly System.IO.Compression. No need for any 3rd party library.

string zipPath = @"c:\example\start.zip";
using (ZipArchive archive = ZipFile.OpenRead(zipPath))
{
    foreach (ZipArchiveEntry entry in archive.Entries)
    {
        Console.WriteLine(entry.FullName);
    }
} 
Colonel Panic
  • 132,665
  • 89
  • 401
  • 465
Csaba Toth
  • 10,021
  • 5
  • 75
  • 121
  • 6
    Works fine and out of the box without 3rd party components. Be sure to add references `System.IO.Compression.dll` and `System.IO.Compression.FileSystem.dll`. – Matt Nov 17 '15 at 12:22
35

DotNetZip - Zip file manipulation in .NET languages

DotNetZip is a small, easy-to-use class library for manipulating .zip files. It can enable .NET applications written in VB.NET, C#, any .NET language, to easily create, read, and update zip files.

sample code to read a zip:

using (var zip = ZipFile.Read(PathToZipFolder))
{
    int totalEntries = zip.Entries.Count; 
    foreach (ZipEntry e in zip.Entries)
    {
        e.FileName ...
        e.CompressedSize ...
        e.LastModified...
    }
}
Cheeso
  • 189,189
  • 101
  • 473
  • 713
Chris Fulstow
  • 41,170
  • 10
  • 86
  • 110
21

If you are using .Net Framework 3.0 or later, check out the System.IO.Packaging Namespace. This will remove your dependancy on an external library.

Specifically check out the ZipPackage Class.

Adrian Clark
  • 12,449
  • 5
  • 36
  • 42
  • 1
    It removes dependency on an external library, but the usability of ZipPackage is really not very good. Everything is a trade off! – Cheeso Mar 08 '09 at 22:46
  • `ZipPackage` is tailored to handle mainly those Microsoft related file formats which internally are zip files, such as: `docx`, `xlsx`, `XPS`, `nupkg`... . From generic zip file point of view these only differ because of the presence of `Content_Type.xml` file placed in the root of the archive. If you cannot use .NET 4.5, but can use .NET 3.0, `ZipPackage` can be perfect given that you produce and consume the files. – Csaba Toth Feb 13 '14 at 23:22
  • 1
    For .NET 4.5 or later though should use `ZipArchive` class for generic zip purposes, see my answer below – Csaba Toth Jul 08 '15 at 22:29
13

Check into SharpZipLib

ZipInputStream inStream = new ZipInputStream(File.OpenRead(fileName));

while (inStream.GetNextEntry())
{

     ZipEntry entry = inStream.GetNextEntry();
     //write out your entry's filename
}
Frederic
  • 2,015
  • 4
  • 20
  • 37
Chris Ballance
  • 33,810
  • 26
  • 104
  • 151
6

Ick - that code using the J# runtime is hideous! And I don't agree that it is the best way - J# is out of support now. And it is a HUGE runtime, if all you want is ZIP support.

How about this - it uses DotNetZip (Free, MS-Public license)

using (ZipFile zip = ZipFile.Read(zipfile) )
{
    bool header = true;
    foreach (ZipEntry e in zip)
    {
        if (header)
        {
            System.Console.WriteLine("Zipfile: {0}", zip.Name);
            if ((zip.Comment != null) && (zip.Comment != ""))
                System.Console.WriteLine("Comment: {0}", zip.Comment);

            System.Console.WriteLine("\n{1,-22} {2,9}  {3,5}   {4,9}  {5,3} {6,8} {0}",
                                     "Filename", "Modified", "Size", "Ratio", "Packed", "pw?", "CRC");
            System.Console.WriteLine(new System.String('-', 80));
            header = false;
        }

        System.Console.WriteLine("{1,-22} {2,9} {3,5:F0}%   {4,9}  {5,3} {6:X8} {0}",
                                 e.FileName,
                                 e.LastModified.ToString("yyyy-MM-dd HH:mm:ss"),
                                 e.UncompressedSize,
                                 e.CompressionRatio,
                                 e.CompressedSize,
                                 (e.UsesEncryption) ? "Y" : "N",
                                 e.Crc32);

        if ((e.Comment != null) && (e.Comment != ""))
            System.Console.WriteLine("  Comment: {0}", e.Comment);
    }
}
Cheeso
  • 189,189
  • 101
  • 473
  • 713
4

If you are like me and do not want to use an external component, here is some code I developed last night using .NET's ZipPackage class.

var zipFilePath = "c:\\myfile.zip";
var tempFolderPath = "c:\\unzipped";

using (Package package = ZipPackage.Open(zipFilePath, FileMode.Open, FileAccess.Read))
{
    foreach (PackagePart part in package.GetParts())
    {
        var target = Path.GetFullPath(Path.Combine(tempFolderPath, part.Uri.OriginalString.TrimStart('/')));
        var targetDir = target.Remove(target.LastIndexOf('\\'));

        if (!Directory.Exists(targetDir))
            Directory.CreateDirectory(targetDir);

        using (Stream source = part.GetStream(FileMode.Open, FileAccess.Read))
        {
            source.CopyTo(File.OpenWrite(target));
        }
    }
}

Things to note:

  • The ZIP archive MUST have a [Content_Types].xml file in its root. This was a non-issue for my requirements as I will control the zipping of any ZIP files that get extracted through this code. For more information on the [Content_Types].xml file, please refer to: A New Standard For Packaging Your Data There is an example file below Figure 13 of the article.

  • This code uses the Stream.CopyTo method in .NET 4.0

AminM
  • 1,658
  • 4
  • 32
  • 48
Joshua
  • 4,099
  • 25
  • 37
  • 1
    Which **month and year** for _MDSN Magazine_ ? https://msdn.microsoft.com/en-us/magazine/ee310108.aspx – Kiquenet Jul 08 '15 at 08:23
0

The best way is to use the .NET built in J# zip functionality, as shown in MSDN: http://msdn.microsoft.com/en-us/magazine/cc164129.aspx. In this link there is a complete working example of an application reading and writing to zip files. For the concrete example of listing the contents of a zip file (in this case a Silverlight .xap application package), the code could look like this:


ZipFile package = new ZipFile(packagePath);
java.util.Enumeration entries = package.entries();
//We have to use Java enumerators because we
//use java.util.zip for reading the .zip files
while ( entries.hasMoreElements() )
{
    ZipEntry entry = (ZipEntry) entries.nextElement();

    if (!entry.isDirectory())
    {
        string name = entry.getName();
        Console.WriteLine("File: " + name + ", size: " + entry.getSize() + ", compressed size: " + entry.getCompressedSize());
    }
    else
    {
        // Handle directories...
    }                        
}

Aydsman had a right pointer, but there are problems. Specifically, you might find issues opening zip files, but is a valid solution if you intend to only create pacakges. ZipPackage implements the abstract Package class and allows manipulation of zip files. There is a sample of how to do it in MSDN: http://msdn.microsoft.com/en-us/library/ms771414.aspx. Roughly the code would look like this:

             string packageRelationshipType = @"http://schemas.microsoft.com/opc/2006/sample/document";
            string resourceRelationshipType = @"http://schemas.microsoft.com/opc/2006/sample/required-resource";
            // Open the Package.
            // ('using' statement insures that 'package' is
            //  closed and disposed when it goes out of scope.)
            foreach (string packagePath in downloadedFiles)
            {
                Logger.Warning("Analyzing " + packagePath);
                using (Package package = Package.Open(packagePath, FileMode.Open, FileAccess.Read))
                {
                    Logger.OutPut("package opened");
                    PackagePart documentPart = null;
                    PackagePart resourcePart = null;

                    // Get the Package Relationships and look for
                    //   the Document part based on the RelationshipType
                    Uri uriDocumentTarget = null;
                    foreach (PackageRelationship relationship in
                        package.GetRelationshipsByType(packageRelationshipType))
                    {
                        // Resolve the Relationship Target Uri
                        //   so the Document Part can be retrieved.
                        uriDocumentTarget = PackUriHelper.ResolvePartUri(
                            new Uri("/", UriKind.Relative), relationship.TargetUri);

                        // Open the Document Part, write the contents to a file.
                        documentPart = package.GetPart(uriDocumentTarget);
                        //ExtractPart(documentPart, targetDirectory);
                        string stringPart = documentPart.Uri.ToString().TrimStart('/');
                        Logger.OutPut("  Got: " + stringPart);
                    }

                    // Get the Document part's Relationships,
                    //   and look for required resources.
                    Uri uriResourceTarget = null;
                    foreach (PackageRelationship relationship in
                        documentPart.GetRelationshipsByType(
                                                resourceRelationshipType))
                    {
                        // Resolve the Relationship Target Uri
                        //   so the Resource Part can be retrieved.
                        uriResourceTarget = PackUriHelper.ResolvePartUri(
                            documentPart.Uri, relationship.TargetUri);

                        // Open the Resource Part and write the contents to a file.
                        resourcePart = package.GetPart(uriResourceTarget);

                        //ExtractPart(resourcePart, targetDirectory);
                        string stringPart = resourcePart.Uri.ToString().TrimStart('/');
                        Logger.OutPut("  Got: " + stringPart);
                    }

                }
            }

The best way seems to use J#, as shown in MSDN: http://msdn.microsoft.com/en-us/magazine/cc164129.aspx

There are pointers to more c# .zip libraries with different licenses, like SharpNetZip and DotNetZip in this article: how to read files from uncompressed zip in c#?. They might be unsuitable because of the license requirements.

Community
  • 1
  • 1
vbroto
  • 6,088
  • 3
  • 22
  • 12
  • 5
    no, this is not the best. The J# runtime is based on an old Java library, the zip stuff has bugs, and it is going out of support. – Cheeso Mar 27 '09 at 05:15