Unzip files programmatically in .net
Asked Answered
S

15

279

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...

Sentimentalize answered 7/5, 2009 at 20:3 Comment(3)
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.Rightism
@Jared - When management gets an idea in their head...Hurlyburly
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"Gentile
P
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.

Piggish answered 7/5, 2009 at 21:2 Comment(5)
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.Sentimentalize
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...).Synder
You don't have to use external libraries to uncompress zip files, you could use Shell32 from System32. Please see https://mcmap.net/q/110248/-c-net-3-5-unzip-zip-file-no-3rd-partyShrink
Code example: https://mcmap.net/q/110249/-how-to-extract-a-folder-from-zip-file-using-sharpziplibSpancel
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!Fallon
L
578

With .NET 4.5 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

Littleton answered 31/1, 2013 at 20:58 Comment(8)
BTW, ZipFile is contained in the assembly System.IO.Compression.FileSystem.Countrified
Which means that you need to add a DLL reference to the framework assembly System.IO.Compression.FileSystem.dll.Rosariarosario
what about .rar files. above code fails to extract .rar files.Calia
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?Heloise
Same with @SoftSan. I got also that error. What to do?Flag
This does not preserve file permissions on unix based systems, so I'd suggest not using it if you need to work on Macs or Linux.Coulombe
@Coulombe 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.Littleton
At 2021, you can directly install the Sytem.IO.Compression NuGet package from package manager rather than attaching the dll manually in reference.Outskirts
O
140

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.

Otherness answered 4/6, 2015 at 19:15 Comment(10)
Did it really take MSFT until 4.5+ to add a native decompressor?Schnapp
@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.Otherness
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.Zebada
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?Heloise
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?Gowk
in .NET 4.6.1 i am not able to get 'ZipArchive' from 'System.IO.Compression.FileSystem', any Idea?Calendar
doesn't work if i concatenate a zip file to another file ( say for example copy \b file1.mp3 + file2.zip file1.mp3 )Tigre
This is great for anyone working on .net standard / core and needs to uncompress a stream instead of a file, as the main nuget packages for working with zip files are not .net standard.Roulade
I had the error 'ZipArchiveEntry' does not contain a definition for 'ExtractToFile' and I found out that, instead, I have to use the static method System.IO.Compression.ZipFileExtensions.ExtractToFile.Untidy
I imported System.IO.Compression, but received this error on build: Error 1 The type or namespace name 'ZipArchive' could not be found (are you missing a using directive or an assembly reference?) C:\Users\Josh\Desktop\delete\WindowsFormsApplication2\WindowsFormsApplication2\Form1.cs 45 25 WindowsFormsApplication2Vogeley
P
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.

Piggish answered 7/5, 2009 at 21:2 Comment(5)
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.Sentimentalize
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...).Synder
You don't have to use external libraries to uncompress zip files, you could use Shell32 from System32. Please see https://mcmap.net/q/110248/-c-net-3-5-unzip-zip-file-no-3rd-partyShrink
Code example: https://mcmap.net/q/110249/-how-to-extract-a-folder-from-zip-file-using-sharpziplibSpancel
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!Fallon
H
60

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

Headband answered 14/9, 2012 at 18:34 Comment(3)
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...Teal
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 !Hostile
Answer deserves +100 bounty. Dependency was minimal, best compatible and easy to learn.Jevon
E
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)...

Each answered 7/5, 2009 at 20:5 Comment(8)
Hmmm... But that's a third party library!Sentimentalize
How very observant of you. Unless you feel like spending several months implemening your own Zip file reader, its your best option.Each
This one is way better than SharpZipLibKisser
@Dan-o Why not Microsoft Compression? nuget.org/packages/Microsoft.Bcl.CompressionSmokechaser
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.Each
@Kisser this is not a dig, but how in your opinion is it better? I'm considering changing over but gathering knowledge before I do?Magnetometer
@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.Kisser
@Kisser appreciate your response, I'll give it a try.Magnetometer
B
13
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

Blumenfeld answered 3/10, 2017 at 14:11 Comment(1)
Source: msdn.microsoft.com/en-us/library/…Lamination
O
4

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

Osborn answered 29/3, 2019 at 16:43 Comment(0)
G
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.

Galton answered 7/5, 2009 at 20:6 Comment(3)
I'm trying out the DeflateStream class. This time I get System.IO.InvalidDataException: Block length does not match with its complement..Sentimentalize
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.Galton
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.Galton
F
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);
            }
        }


    }
}
Firstnighter answered 13/9, 2013 at 19:44 Comment(1)
This requires dot net 4.5 - just a note as others who answered with ZipFile noted and I am still using 3.5.Affiliation
T
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.

Tanika answered 12/5, 2014 at 14:30 Comment(0)
B
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.

Barratry answered 7/5, 2009 at 20:9 Comment(0)
R
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.

Radiotelegram answered 7/11, 2013 at 22:51 Comment(0)
H
0

From Embed Ressources:

using (Stream _pluginZipResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(programName + "." + "filename.zip"))
{
    using (ZipArchive zip = new ZipArchive(_pluginZipResourceStream))
    {
        zip.ExtractToDirectory(Application.StartupPath);
    }
}
Hiddenite answered 13/1, 2016 at 15:31 Comment(0)
P
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());
Placebo answered 7/9, 2017 at 10:6 Comment(0)
D
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; }
    }        
Decker answered 8/8, 2018 at 12:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.