在 .net 中以编程方式解压缩文件

发布于 2024-07-18 08:24:15 字数 649 浏览 6 评论 0原文

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

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

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

我现在意识到 .zip 文件与 .gz 文件不同,并且 GZip< /code> 与 Zip 不同。

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

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

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

或者还有其他方法可以做到吗? 我更喜欢用代码来完成,而不需要下载任何第三方库或应用程序; 安全部门对此不太感兴趣......

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(15

∞梦里开花 2024-07-25 08:24:15

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

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

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

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

淤浪 2024-07-25 08:24:15

对于 .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 的引用。

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.

执笏见 2024-07-25 08:24:15

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

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.

初与友歌 2024-07-25 08:24:15

免费,且无外部 DLL 文件。 一切都在一个 CS 文件中。 一个下载只是 CS 文件,另一个下载是一个非常容易理解的示例。 今天刚尝试过,我简直不敢相信设置如此简单。 第一次尝试就成功了,没有错误,什么也没有。

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

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

奈何桥上唱咆哮 2024-07-25 08:24:15

使用 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)...

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

以为你会在 2024-07-25 08:24:15
String ZipPath = @"c:\my\data.zip";
String extractPath = @"d:\\myunzips";
ZipFile.ExtractToDirectory(ZipPath, extractPath);

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

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

沧桑㈠ 2024-07-25 08:24:15

这样就可以了 System.IO. Compression.ZipFile.ExtractToDirectory(ZipName, ExtractToPath)

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

单挑你×的.吻 2024-07-25 08:24:15

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

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

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

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.

苏别ゝ 2024-07-25 08:24:15

我用它来压缩或解压缩多个文件。 正则表达式的东西不是必需的,但我用它来更改日期戳并删除不需要的下划线。 我在压缩>>中使用空字符串 如果需要,为所有文件添加前缀的 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);
            }
        }


    }
}

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


    }
}
烟织青萝梦 2024-07-25 08:24:15

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

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

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.

暖心男生 2024-07-25 08:24:15

来自此处

写入的压缩 GZipStream 对象
到扩展名为 .gz 的文件即可
使用许多常见的解压缩
压缩工具; 然而,这个类
本身并不提供
添加文件到或的功能
从 .zip 存档中提取文件。

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.

樱花落人离去 2024-07-25 08:24:15

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

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

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.

我乃一代侩神 2024-07-25 08:24:15

来自嵌入资源:

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

From Embed Ressources:

using (Stream _pluginZipResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(programName + "." + "filename.zip"))
{
    using (ZipArchive zip = new ZipArchive(_pluginZipResourceStream))
    {
        zip.ExtractToDirectory(Application.StartupPath);
    }
}
穿越时光隧道 2024-07-25 08:24:15

到目前为止,我一直在使用 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());

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());
我的鱼塘能养鲲 2024-07-25 08:24:15

您可以使用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; }
    }        

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; }
    }        
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文