我正在尝试以编程方式解压缩压缩文件。
我尝试在.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);
}
}
}
上面的代码直接取自微软的文档:http://msdn.microsoft.com/en-us/library/ms404280(v=vs.110).aspx
ZipFile包含在系统集system . io . compress . filesystem中。(由于nateirvin……见下面的评论)。您需要向框架程序集system . io . compress . filesystem . DLL添加一个DLL引用
到目前为止,我一直在使用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());
对于。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的引用。
我用它来压缩或解压缩多个文件。Regex的东西不是必需的,但我用它来更改日期戳和删除不需要的下划线。如果需要,我使用压缩>> 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);
}
}
}
}