290

I am trying to programatically unzip a zipped file.

I have tried using the System.IO.Compression.GZipStream class in .NET, but when my app runs (actually a unit test) I get this exception:

System.IO.InvalidDataException: The magic number in GZip header is not correct. Make sure you are passing in a GZip stream..

I now realize that a .zip file is not the same as a .gz file, and that GZip is not the same as Zip.

However, since I'm able to extract the file by manually double clicking the zipped file and then clicking the "Extract all files"-button, I think there should be a way of doing that in code as well.

Therefore I've tried to use Process.Start() with the path to the zipped file as input. This causes my app to open a Window showing the contents in the zipped file. That's all fine, but the app will be installed on a server with none around to click the "Extract all files"-button.

So, how do I get my app to extract the files in the zipped files?

Or is there another way to do it? I prefer doing it in code, without downloading any third party libraries or apps; the security department ain't too fancy about that...

3
  • 18
    Your security department is happier with you writing your own code for something than using a library that has been debugged and looked at by presumably many eyes? You can use a library AND "do it in code" (get the source and compile it yourself) but I see reinventing the wheel as a bigger problem than any security issues brought about by using a tried and true library. Commented May 7, 2009 at 20:10
  • 12
    @Jared - When management gets an idea in their head... Commented May 7, 2009 at 20:16
  • 5
    There is less risk for security department if you get a third party product. Just download dotnetzip and rename it "[insert company name].ziplibrary.dll" Commented May 7, 2009 at 21:41

16 Answers 16

592

Starting with .NET 4.5 (and above) you can now unzip files using the .NET framework:

using System;
using System.IO;

namespace ConsoleApplication
{
  class Program
  {
    static void Main(string[] args)
    {
      string startPath = @"c:\example\start";
      string zipPath = @"c:\example\result.zip";
      string extractPath = @"c:\example\extract";

      System.IO.Compression.ZipFile.CreateFromDirectory(startPath, zipPath);
      System.IO.Compression.ZipFile.ExtractToDirectory(zipPath, extractPath);
    }
  }
}

The above code was taken directly from Microsoft's documentation: http://msdn.microsoft.com/en-us/library/ms404280(v=vs.110).aspx

ZipFile is contained in the assembly System.IO.Compression.FileSystem. (Thanks nateirvin...see comment below). You need to add a DLL reference to the framework assembly System.IO.Compression.FileSystem.dll

Sign up to request clarification or add additional context in comments.

10 Comments

BTW, ZipFile is contained in the assembly System.IO.Compression.FileSystem.
Which means that you need to add a DLL reference to the framework assembly System.IO.Compression.FileSystem.dll.
what about .rar files. above code fails to extract .rar files.
I tried this in my asp.net core web api, it read first entry fine, but on second entry it always give error A local file header is corrupt. Any though on this?
@Aidan that's good to know, though, it would be a good recommendation to not use .NET on Mac/Linux if at all possible. Where it isn't, this is helpful. Thanks.
|
147

For .Net 4.5+

It is not always desired to write the uncompressed file to disk. As an ASP.Net developer, I would have to fiddle with permissions to grant rights for my application to write to the filesystem. By working with streams in memory, I can sidestep all that and read the files directly:

using (ZipArchive archive = new ZipArchive(postedZipStream))
{
    foreach (ZipArchiveEntry entry in archive.Entries)
    {
         var stream = entry.Open();
         //Do awesome stream stuff!!
    }
}

Alternatively, you can still write the decompressed file out to disk by calling ExtractToFile():

using (ZipArchive archive = ZipFile.OpenRead(pathToZip))
{
    foreach (ZipArchiveEntry entry in archive.Entries)
    {
        entry.ExtractToFile(Path.Combine(destination, entry.FullName));
    }
} 

To use the ZipArchive class, you will need to add a reference to the System.IO.Compression namespace and to System.IO.Compression.FileSystem.

10 Comments

Did it really take MSFT until 4.5+ to add a native decompressor?
@JohnPeters GZipStream was added back in .Net 2.0 (msdn.microsoft.com/en-us/library/…). However, it didn't make it easy to work with multiple files in an archive in memory. The new ZipArchive object fits the bill nicely.
This is a particularly good alternative because it allows unzipping without using the file-system (in my case I am working with embedded resources), and it's also not a third-party extension.
Why should I use a foreach loop to ExtractToFile when I can just use ZipFile.ExtractToDirectory(inputFile, outputDir); What is the advantage of the first method?
in .NET 4.6.1 i am not able to get 'ZipArchive' from 'System.IO.Compression.FileSystem', any Idea?
|
67

We have used SharpZipLib successfully on many projects. I know it's a third party tool, but source code is included and could provide some insight if you chose to reinvent the wheel here.

5 Comments

I tried using SharpZipLib and it worked fine. I guess I'll have to see if the prohibition against third party libs and apss is a strict rule or more of a guidline.
I don't know about your company, but my experience has always been that it's possible to get an exception to that sort of rule if you write up a business case description of why you want the exception. Point out the cost savings v. DIY, as well as the fact that the source can be examined. As a fallback, you can often get permission to use the source even if they won't let you use the dll--then just compile it yourself (or at least the parts you actually need to use...).
You don't have to use external libraries to uncompress zip files, you could use Shell32 from System32. Please see stackoverflow.com/a/43066281/948694
We are using SharpZipLib, and hitting problems unpacking files that have the Danish character 'ø' in their names. We'll try the native Zip unpack instead - thanks!
60
+100

Free, and no external DLL files. Everything is in one CS file. One download is just the CS file, another download is a very easy to understand example. Just tried it today and I can't believe how simple the setup was. It worked on first try, no errors, no nothing.

https://github.com/jaime-olivares/zipstorer

3 Comments

Spoke too soon! I want to inflate the files from an http download stream instantly. This does not work since it is using Seek operations on the stream :( Well, thanks to the source code I can write my own ZipStream now...
the best solution to my problem,since im writing an updater app and i cant involve any DLLs in the extraction process since then i would have to update those too....this is good.thank you !
Answer deserves +100 bounty. Dependency was minimal, best compatible and easy to learn.
28

Use the DotNetZip library at http://www.codeplex.com/DotNetZip

class library and toolset for manipulating zip files. Use VB, C# or any .NET language to easily create, extract, or update zip files...

DotNetZip works on PCs with the full .NET Framework, and also runs on mobile devices that use the .NET Compact Framework. Create and read zip files in VB, C#, or any .NET language, or any scripting environment...

If all you want is a better DeflateStream or GZipStream class to replace the one that is built-into the .NET BCL, DotNetZip has that, too. DotNetZip's DeflateStream and GZipStream are available in a standalone assembly, based on a .NET port of Zlib. These streams support compression levels and deliver much better performance than the built-in classes. There is also a ZlibStream to complete the set (RFC 1950, 1951, 1952)...

8 Comments

Hmmm... But that's a third party library!
How very observant of you. Unless you feel like spending several months implemening your own Zip file reader, its your best option.
This one is way better than SharpZipLib
Your're asking me questions about an answer that is nearly 5 years old. Do some research. I'm sure you will find an answer.
@PhilCooper This is a very old question I recommend using the built-in System.IO.Compression.ZipFile. IIRC I had really bad experiences with SharpZipLib in the past based on my experience of producing thousands of zips on the fly.
|
15
String ZipPath = @"c:\my\data.zip";
String extractPath = @"d:\\myunzips";
ZipFile.ExtractToDirectory(ZipPath, extractPath);

To use the ZipFile class, you must add a reference to the System.IO.Compression.FileSystem assembly in your project

1 Comment

5

This will do it System.IO.Compression.ZipFile.ExtractToDirectory(ZipName, ExtractToPath)

Comments

2

Standard zip files normally use the deflate algorithm.

To extract files without using third party libraries use DeflateStream. You'll need a bit more information about the zip file archive format as Microsoft only provides the compression algorithm.

You may also try using zipfldr.dll. It is Microsoft's compression library (compressed folders from the Send to menu). It appears to be a com library but it's undocumented. You may be able to get it working for you through experimentation.

3 Comments

I'm trying out the DeflateStream class. This time I get System.IO.InvalidDataException: Block length does not match with its complement..
As I said above, Microsoft only provided the algorithm. You'll need info on the zip archive format as well. en.wikipedia.org/wiki/ZIP_(file_format) should get you started. See the references at the bottom of the page for links to more detailed info.
I also stumbled acrossed System.IO.Packaging.Package in .NET 3.5. It looks like it may do the trick though its not very intuitive.
2

I use this to either zip or unzip multiple files. The Regex stuff is not required, but I use it to change the date stamp and remove unwanted underscores. I use the empty string in the Compress >> zipPath string to prefix something to all files if required. Also, I usually comment out either Compress() or Decompress() based on what I am doing.

using System;
using System.IO.Compression;
using System.IO;
using System.Text.RegularExpressions;

namespace ZipAndUnzip
{
    class Program
    {
        static void Main(string[] args)
        {
            var directoryPath = new DirectoryInfo(@"C:\your_path\");

            Compress(directoryPath);
            Decompress(directoryPath);
        }

        public static void Compress(DirectoryInfo directoryPath)
        {
            foreach (DirectoryInfo directory in directoryPath.GetDirectories())
            {
                var path = directoryPath.FullName;
                var newArchiveName = Regex.Replace(directory.Name, "[0-9]{8}", "20130913");
                newArchiveName = Regex.Replace(newArchiveName, "[_]+", "_");
                string startPath = path + directory.Name;
                string zipPath = path + "" + newArchiveName + ".zip";

                ZipFile.CreateFromDirectory(startPath, zipPath);
            }

        }

        public static void Decompress(DirectoryInfo directoryPath)
        {
            foreach (FileInfo file in directoryPath.GetFiles())
            {
                var path = directoryPath.FullName;
                string zipPath = path + file.Name;
                string extractPath = Regex.Replace(path + file.Name, ".zip", "");

                ZipFile.ExtractToDirectory(zipPath, extractPath);
            }
        }


    }
}

1 Comment

This requires dot net 4.5 - just a note as others who answered with ZipFile noted and I am still using 3.5.
2

You can do it all within .NET 3.5 using DeflateStream. The thing lacking in .NET 3.5 is the ability to process the file header sections that are used to organize the zipped files. PKWare has published this information, which you can use to process the zip file after you create the structures that are used. It is not particularly onerous, and it a good practice in tool building without using 3rd party code.

It isn't a one line answer, but it is completely doable if you are willing and able to take the time yourself. I wrote a class to do this in a couple of hours and what I got from that is the ability to zip and unzip files using .NET 3.5 only.

Comments

2

In .net 4.8.1 best alternative can be using System.IO.Compression.ZipFile instead of System.IO.Compression.FileStream. As dll file System.IO.Compression.FileStream do not exist on nuget server and should be added manually using another link.

Example:

System.IO.Compression.ZipFile.ExtractToDirectory(zipPath, temp_extracted);

Or if you are interested opening file and processing it using a loop.

using (ZipArchive archive = ZipFile.OpenRead(zipPath))
{
    foreach (ZipArchiveEntry entry in archive.Entries)
    {
        Console.WriteLine("Extracting: " + entry.Name);
        entry.ExtractToFile(destinationPath);
    }
}

Comments

1

From here :

Compressed GZipStream objects written to a file with an extension of .gz can be decompressed using many common compression tools; however, this class does not inherently provide functionality for adding files to or extracting files from .zip archives.

Comments

0

I found out about this one (Unzip package on NuGet) today, since I ran into a hard bug in DotNetZip, and I realized there hasn't been really that much work done on DotNetZip for the last two years.

The Unzip package is lean, and it did the job for me - it didn't have the bug that DotNetZip had. Also, it was a reasonably small file, relying upon the Microsoft BCL for the actual decompression. I could easily make adjustments which I needed (to be able to keep track of the progress while decompressing). I recommend it.

Comments

0

From Embed Ressources:

using (Stream _pluginZipResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(programName + "." + "filename.zip"))
{
    using (ZipArchive zip = new ZipArchive(_pluginZipResourceStream))
    {
        zip.ExtractToDirectory(Application.StartupPath);
    }
}

Comments

0

Until now, I was using cmd processes in order to extract an .iso file, copy it into a temporary path from server and extracted on a usb stick. Recently I've found that this is working perfectly with .iso's that are less than 10Gb. For a iso like 29Gb this method gets stuck somehow.

    public void ExtractArchive()
    {
        try
        {

            try
            {
                Directory.Delete(copyISOLocation.OutputPath, true); 
            }
            catch (Exception e) when (e is IOException || e is UnauthorizedAccessException)
            {
            }

            Process cmd = new Process();
            cmd.StartInfo.FileName = "cmd.exe";
            cmd.StartInfo.RedirectStandardInput = true;
            cmd.StartInfo.RedirectStandardOutput = true;
            cmd.StartInfo.CreateNoWindow = true;
            cmd.StartInfo.UseShellExecute = false;
            cmd.StartInfo.WindowStyle = ProcessWindowStyle.Normal;

            //stackoverflow
            cmd.StartInfo.Arguments = "-R";

            cmd.Disposed += (sender, args) => {
                Console.WriteLine("CMD Process disposed");
            };
            cmd.Exited += (sender, args) => {
                Console.WriteLine("CMD Process exited");
            };
            cmd.ErrorDataReceived += (sender, args) => {
                Console.WriteLine("CMD Process error data received");
                Console.WriteLine(args.Data);
            };
            cmd.OutputDataReceived += (sender, args) => {
                Console.WriteLine("CMD Process Output data received");
                Console.WriteLine(args.Data);
            };

            //stackoverflow


            cmd.Start();

            cmd.StandardInput.WriteLine("C:");
            //Console.WriteLine(cmd.StandardOutput.Read());
            cmd.StandardInput.Flush();

            cmd.StandardInput.WriteLine("cd C:\\\"Program Files (x86)\"\\7-Zip\\");
            //Console.WriteLine(cmd.StandardOutput.ReadToEnd());
            cmd.StandardInput.Flush();

            cmd.StandardInput.WriteLine(string.Format("7z.exe x -o{0} {1}", copyISOLocation.OutputPath, copyISOLocation.TempIsoPath));
            //Console.WriteLine(cmd.StandardOutput.ReadToEnd());
            cmd.StandardInput.Flush();
            cmd.StandardInput.Close();
            cmd.WaitForExit();
            Console.WriteLine(cmd.StandardOutput.ReadToEnd());
            Console.WriteLine(cmd.StandardError.ReadToEnd());

Comments

0

you can use Info-unzip command line cod.you only need to download unzip.exe from Info-unzip official website.

 internal static void Unzip(string sorcefile)
    {
        try
        {
            AFolderFiles.AFolderFilesDelete.DeleteFolder(TempBackupFolder); // delete old folder   
            AFolderFiles.AFolderFilesCreate.CreateIfNotExist(TempBackupFolder); // delete old folder   
           //need to Command command also to export attributes to a excel file
            System.Diagnostics.Process process = new System.Diagnostics.Process();
            System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
            startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; // window type
            startInfo.FileName = UnzipExe;
            startInfo.Arguments = sorcefile + " -d " + TempBackupFolder;
            process.StartInfo = startInfo;
            process.Start();
            //string result = process.StandardOutput.ReadToEnd();
            process.WaitForExit();
            process.Dispose();
            process.Close();
        }
        catch (Exception ex){ throw ex; }
    }        

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.