我正在尝试以编程方式解压缩压缩文件。
我曾尝试在 .NET 中使用 System.IO.Compression.GZipStream
类,但是当我的应用程序运行(实际上是单元测试)时,我得到了这个异常:
System.IO.InvalidDataException:GZip 标头中的幻数不正确。确保您传递的是 GZip 流。
我现在意识到 .zip
文件与 .gz
文件不同,并且 GZip
与 Zip
不同。
但是,由于我可以通过手动双击压缩文件然后单击“提取所有文件”按钮来提取文件,因此我认为也应该有一种方法可以在代码中执行此操作。
因此,我尝试使用带有压缩文件路径的 Process.Start()
作为输入。这会导致我的应用程序打开一个窗口,显示压缩文件中的内容。这一切都很好,但是该应用程序将安装在一个没有周围的服务器上单击“提取所有文件”按钮。
那么,如何让我的应用程序提取压缩文件中的文件?
还是有其他方法可以做到这一点?我更喜欢用代码来做,不下载任何第三方库或应用程序;安全部门不太喜欢这个...
使用 .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 引用
对于 .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
的引用。
ZipArchive
对象非常符合要求。
ZipFile.ExtractToDirectory(inputFile, outputDir);
时,为什么还要使用 foreach
循环到 ExtractToFile
第一种方法的优点是什么?
我们已在许多项目中成功使用 SharpZipLib。我知道它是第三方工具,但包含源代码,如果您选择在这里重新发明轮子,可以提供一些见解。
免费,并且没有外部 DLL 文件。一切都在一个 CS 文件中。一个下载只是 CS 文件,另一个下载是一个非常容易理解的示例。今天刚试过,我不敢相信设置是多么简单。它在第一次尝试时有效,没有错误,没有任何东西。
https://github.com/jaime-olivares/zipstorer
在 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)...
String ZipPath = @"c:\my\data.zip";
String extractPath = @"d:\\myunzips";
ZipFile.ExtractToDirectory(ZipPath, extractPath);
要使用 ZipFile 类,您必须在项目中添加对 System.IO.Compression.FileSystem 程序集的引用
这样就可以了System.IO.Compression.ZipFile.ExtractToDirectory(ZipName, ExtractToPath)
标准 zip 文件通常使用 deflate 算法。
要在不使用第三方库的情况下提取文件,请使用 DeflateStream。您需要更多有关 zip 文件存档格式的信息,因为 Microsoft 仅提供压缩算法。
您也可以尝试使用 zipfldr.dll。它是 Microsoft 的压缩库(发送到菜单中的压缩文件夹)。它似乎是一个 com 库,但没有记录。你也许可以通过实验让它为你工作。
我用它来压缩或解压缩多个文件。 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);
}
}
}
}
您可以使用 DeflateStream 在 .NET 3.5 中完成所有操作。 .NET 3.5 中缺少的是处理用于组织压缩文件的文件头部分的能力。 PKWare 已发布此信息,您可以在创建所使用的结构后使用这些信息来处理 zip 文件。它不是特别繁重,并且在不使用 3rd 方代码的情况下构建工具是一种很好的做法。
这不是一个单一的答案,但如果你愿意并且能够自己花时间,它是完全可行的。我在几个小时内编写了一个类来完成这项工作,我从中得到的是仅使用 .NET 3.5 压缩和解压缩文件的能力。
从 here :
写入扩展名为 .gz 的文件的压缩 GZipStream 对象可以使用许多常用压缩工具进行解压缩;但是,此类本身并不提供将文件添加到 .zip 档案或从 .zip 档案中提取文件的功能。
我今天发现了 this one(在 NuGet 上解压缩包),因为我在 DotNetZip 中遇到了一个严重的错误,并且我意识到过去两年在 DotNetZip 上并没有做太多的工作。
Unzip 包很精简,它为我完成了这项工作——它没有 DotNetZip 的错误。此外,它是一个相当小的文件,依赖于 Microsoft BCL 进行实际解压缩。我可以轻松地进行我需要的调整(以便能够在解压缩时跟踪进度)。我推荐它。
来自嵌入资源:
using (Stream _pluginZipResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(programName + "." + "filename.zip"))
{
using (ZipArchive zip = new ZipArchive(_pluginZipResourceStream))
{
zip.ExtractToDirectory(Application.StartupPath);
}
}
到目前为止,我一直在使用 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());
您可以使用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; }
}
不定期副业成功案例分享
ZipFile
包含在程序集System.IO.Compression.FileSystem
中。System.IO.Compression.FileSystem.dll
。A local file header is corrupt
。有这方面的吗?