views:

2780

answers:

8

How to 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?

+7  A: 

Check into SharpZipLib (roughly coded up)

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

While (isnStream.GetNextEntry)
{

     entry = inStream.GetNextEntry();
     //write out your entry's filename
}
Chris Ballance
link: http://www.icsharpcode.net/OpenSource/SharpZipLib/
dnolan
+2  A: 

There are a number of libraries for .NET available, with different licensing requirements.

Here is a intro article on the topic: Article

pearcewg
Why is this voted down? It answers the question.
Kev
+5  A: 

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...
    }
}
cxfx
Why is this voted down? It answers the question.
Kev
+10  A: 

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.

Aydsman
+1 to this answer!
Mat Nadrofsky
It removes dependency on an external library, but the usability of ZipPackage is really not very good. Everything is a trade off!
Cheeso
+2  A: 

I'm relatively new here so maybe I'm not understanding what's going on. :-) There are currently 4 answers on this thread where the two best answers have been voted down. (Pearcewg's and cxfx's) The article pointed to by pearcewg is important because it clarifies some licensing issues with SharpZipLib. We recently evaluated several .Net compression libraries, and found that DotNetZip is currently the best aleternative.

Very short summary:

  • System.IO.Packaging is significantly slower than DotNetZip.

  • SharpZipLib is GPL - see article.

So for starters, I voted those two answers up.

Kim.

Kim Major
The GPL itself specifically addresses the issue of portions of a program that are not "derivative" of the GPLed code, and their right to be licensed independently. I fail to see how SharpZipLib being GPL is a significant issue.
GalacticCowboy
GC, you are saying that if a group or org has a problem with the GPL, then the group is wrong? Or is it that you just cannot possibly understand how anyone would have an issue with the GPL, ever? It's not so hard to believe. The press is rife with stories of expensive legal tests.
Cheeso
Yeah, GPL is viral. If he's making commercial closed source software, and he links his code to a GPLed library, then he has to release his source under a GPL compatible license. So yes, the fact that the SharpZibLib is GPL is a significant issue.
cdmckay
+1  A: 

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: http://stackoverflow.com/questions/265549/how-to-read-files-from-uncompressed-zip-in-c. They might be unsuitable because of the license requirements.

vbroto
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
+3  A: 

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
A: 

Please see this topic: Listing Zip contents. It's an article from a commercial component UltimateZip. If you prefer a FREE one, you may need DotNetZip or SharpZipLib.

Mark Attwood