250

我正在尝试以编程方式解压缩压缩文件。

我曾尝试System.IO.Compression.GZipStream在 .NET 中使用该类,但是当我的应用程序运行(实际上是单元测试)时,我得到了这个异常:

System.IO.InvalidDataException:GZip 标头中的幻数不正确。确保您传递的是 GZip 流。

我现在意识到.zip文件与.gz文件不同,并且GZipZip.

但是,由于我可以通过手动双击压缩文件然后单击“提取所有文件”按钮来提取文件,因此我认为也应该有一种方法可以在代码中执行此操作。

因此,我尝试使用Process.Start()压缩文件的路径作为输入。这会导致我的应用程序打开一个窗口,显示压缩文件中的内容。这一切都很好,但是该应用程序将安装在一个没有周围的服务器上单击“提取所有文件”按钮。

那么,如何让我的应用程序提取压缩文件中的文件?

还是有其他方法可以做到这一点?我更喜欢用代码来做,不下载任何第三方库或应用程序;安全部门不太喜欢这个...

4

15 回答 15

534

使用.NET 4.5,您现在可以使用 .NET 框架解压缩文件:

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);
    }
  }
}

上面的代码直接取自微软的文档: http: //msdn.microsoft.com/en-us/library/ms404280 (v=vs.110).aspx

ZipFile包含在程序集中System.IO.Compression.FileSystem。(感谢 nateirvin ......见下面的评论)。您需要添加对框架程序集的 DLL 引用System.IO.Compression.FileSystem.dll

于 2013-01-31T20:58:31.630 回答
120

对于 .Net 4.5+

并不总是希望将未压缩的文件写入磁盘。作为 ASP.Net 开发人员,我将不得不摆弄权限来授予我的应用程序写入文件系统的权限。通过使用内存中的流,我可以回避所有这些并直接读取文件:

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

或者,您仍然可以通过调用将解压缩文件写入磁盘ExtractToFile()

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

要使用ZipArchive该类,您需要添加对System.IO.Compression命名空间和System.IO.Compression.FileSystem.

于 2015-06-04T19:15:50.217 回答
63

我们已经在许多项目中成功使用了SharpZipLib 。我知道它是第三方工具,但包含源代码,如果您选择在这里重新发明轮子,可以提供一些见解。

于 2009-05-07T21:02:31.667 回答
57

免费,并且没有外部 DLL 文件。一切都在一个 CS 文件中。一个下载只是 CS 文件,另一个下载是一个非常容易理解的示例。今天刚试过,我不敢相信设置是多么简单。它在第一次尝试时有效,没有错误,没有任何东西。

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

于 2012-09-14T18:34:22.837 回答
28

使用位于http://www.codeplex.com/DotNetZip的 DotNetZip 库

用于操作 zip 文件的类库和工具集。使用 VB、C# 或任何 .NET 语言轻松创建、提取或更新 zip 文件...

DotNetZip 可以在带有完整 .NET Framework 的 PC 上运行,也可以在使用 .NET Compact Framework 的移动设备上运行。在 VB、C# 或任何 .NET 语言或任何脚本环境中创建和读取 zip 文件...

如果您只需要一个更好的 DeflateStream 或 GZipStream 类来替换 .NET BCL 中内置的类,DotNetZip 也有。DotNetZip 的 DeflateStream 和 GZipStream 可用于独立程序集,基于 Zlib 的 .NET 端口。这些流支持压缩级别并提供比内置类更好的性能。还有一个 ZlibStream 来完成集合(RFC 1950、1951、1952)...

于 2009-05-07T20:05:58.557 回答
11
String ZipPath = @"c:\my\data.zip";
String extractPath = @"d:\\myunzips";
ZipFile.ExtractToDirectory(ZipPath, extractPath);

要使用 ZipFile 类,您必须在项目中添加对 System.IO.Compression.FileSystem 程序集的引用

于 2017-10-03T14:11:01.157 回答
4

这会做到的System.IO.Compression.ZipFile.ExtractToDirectory(ZipName, ExtractToPath)

于 2019-03-29T16:43:22.480 回答
2

标准 zip 文件通常使用 deflate 算法。

要在不使用第三方库的情况下提取文件,请使用 DeflateStream。您需要更多有关 zip 文件存档格式的信息,因为 Microsoft 仅提供压缩算法。

您也可以尝试使用 zipfldr.dll。它是 Microsoft 的压缩库(发送到菜单中的压缩文件夹)。它似乎是一个 com 库,但没有记录。你也许可以通过实验让它为你工作。

于 2009-05-07T20:06:35.183 回答
2

我用它来压缩或解压缩多个文件。Regex 的东西不是必需的,但我用它来更改日期戳并删除不需要的下划线。如果需要,我使用 Compress >> zipPath 字符串中的空字符串为所有文件添加前缀。另外,我通常会根据我正在做的事情注释掉 Compress() 或 Decompress() 。

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);
            }
        }


    }
}
于 2013-09-13T19:44:55.313 回答
2

您可以使用 DeflateStream 在 .NET 3.5 中完成所有操作。.NET 3.5 中缺少的是处理用于组织压缩文件的文件头部分的能力。PKWare 已发布此信息,您可以在创建所使用的结构后使用这些信息来处理 zip 文件。它不是特别繁重,并且在不使用 3rd 方代码的情况下构建工具是一种很好的做法。

这不是一个单一的答案,但如果你愿意并且能够自己花时间,它是完全可行的。我在几个小时内编写了一个类来完成这项工作,我从中得到的是仅使用 .NET 3.5 压缩和解压缩文件的能力。

于 2014-05-12T14:30:03.557 回答
1

这里

写入扩展名为 .gz 的文件的压缩 GZipStream 对象可以使用许多常用压缩工具进行解压缩;但是,此类本身并不提供将文件添加到 .zip 档案或从 .zip 档案中提取文件的功能。

于 2009-05-07T20:09:25.083 回答
0

我今天发现了这个(在 NuGet 上解压缩包),因为我在 DotNetZip 中遇到了一个严重的错误,我意识到过去两年在 DotNetZip 上并没有做太多的工作。

Unzip 包很精简,它为我完成了这项工作——它没有 DotNetZip 的错误。此外,它是一个相当小的文件,依赖于 Microsoft BCL 进行实际解压缩。我可以轻松地进行我需要的调整(以便能够在解压缩时跟踪进度)。我推荐它。

于 2013-11-07T22:51:30.477 回答
0

来自嵌入资源:

using (Stream _pluginZipResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(programName + "." + "filename.zip"))
{
    using (ZipArchive zip = new ZipArchive(_pluginZipResourceStream))
    {
        zip.ExtractToDirectory(Application.StartupPath);
    }
}
于 2016-01-13T15:31:44.880 回答
0

到目前为止,我一直在使用 cmd 进程来提取 .iso 文件,将其从服务器复制到临时路径中,然后提取到 U 盘上。最近我发现这与小于 10Gb 的 .iso 完美配合。对于像 29Gb 这样的 iso,这种方法会以某种方式卡住。

    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());
于 2017-09-07T10:06:28.923 回答
0

您可以使用Info-unzip命令行cod。您只需要从Info-unzip官网下载unzip.exe。

 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; }
    }        
于 2018-08-08T12:24:59.457 回答