我知道有可用于处理 ZIP 文件的库。而且,您也可以使用 Windows 内置的功能来处理 ZIP 文件。
但是,我想知道是否有人已经弄清楚如何使用 .NET 中的 System.IO.Compression 命名空间中内置的工具来读取/写入 ZIP 文件?或者,仅使用这个命名空间是不可能的吗?
更新:我似乎有人评论说 System.IO.Packaging 命名空间对此也可能有用。有谁知道具体怎么做吗?
MSDN 有一个完整的 example http://msdn.microsoft.com/en-us/library/system.io.packaging.zippackage.aspx 使用 ZipPackage 类。 需要 .NET 3.5。
其他答案已经过时了十年。
.NET 4.5 对 System.IO.Compression 添加了广泛的改进。
它现在可以很好地操作 .zip 文件,甚至可以将 zip 中的各个文件公开为能够读取或写入的流,而无需提取和压缩文件的步骤。
全部内置,不再需要第三方库。
例如:
using System;
using System.IO.Compression;
class Program
{
static void Main(string[] args)
{
string startPath = @".\start";
string zipPath = @".\result.zip";
string extractPath = @".\extract";
ZipFile.CreateFromDirectory(startPath, zipPath);
ZipFile.ExtractToDirectory(zipPath, extractPath);
}
}
戴夫,非常好!我不知道那里有。
现在我知道要寻找什么了,我找到了一篇文章,其中包含有关如何使用它的小代码示例: http://weblogs.asp.net/jgalloway/archive/2007/10/25/creating-zip-archives-in-net-without-an-external-library-like-sharpziplib.aspx
在相关说明中,我还发现了 DotNetZip 项目,它看起来非常易于使用。
您将需要使用第三方库,例如 http://www.codeplex.com/DotNetZip,而不是尝试使用 GZipStream 或 DeflateStream 来读取 zip 文件。
.NET 中的 ***Stream 类可以让您读取或写入压缩字节流。 这些类不读取或写入 zip 文件。 zip 文件是由“信封”或标头包围的压缩数据。 将其视为元数据 - 它包括文件名、时间戳、CRC 和一堆其他内容。 **Stream 类仅生成压缩数据流,不知道如何生成或使用元数据,这在 PKWare 维护的 PKZip 格式规范中进行了描述。
DotNetZip 等第三方库处理 ZIP 存档中的元数据。他们可能会也可能不会使用 System.IO. Compression.DeflateStream() 类来生成压缩的字节流。 例如,在以前的版本中,DotNetZip 使用内置的 DeflateStream。 从 v1.7 开始,DotNetZip 包含了自己的 DeflateStream,它比 .NET Framework 中提供的 DeflateStream 更高效。 作为一个额外的好处,DotNetZip 中嵌入的 DeflateStream 允许在 .NET Compact Framework 2.0 上使用 DotNetZip,该框架缺少 System.IO.Compression.DeflateStream。 (Compact Framework 3.5 中添加)
如果您有更多问题,DotNetZip 网站上有一个很好的论坛。 C# 代码示例:
try
{
using (ZipFile zip = new ZipFile())
{
zip.AddDirectory(DirectoryToZip); // recurses subdirs
zip.Save(Filename);
}
}
catch (System.Exception ex1)
{
System.Console.Error.WriteLine("exception: " + ex1);
}
自 .NET 4.5 起,Microsoft 向 System.IO.Compression
命名空间提供了
ZipArchive类。 不过,与该命名空间中的其他类不同,如
GZipStream
和 Deflate
流,ZipArchive
需要引用 System.IO.Compression.dll 程序集。
使用起来相当简单,上面的 MSDN 链接提供了一些很好的示例。
此外,Microsoft 还创建了 Microsoft Compression NuGet 包,它向 Windows Phone 8 和其他可移植类库添加了对
ZipArchive
及相关类的支持
一个旧线程,但我想分享我发现的最简单的解决方案,仅在一行代码中使用 System.IO.Compression(读/写):
System.IO.Compression.ZipFile.ExtractToDirectory(sourceArchiveFileName, destinationDirectoryName);
System.IO.Compression.ZipFile.CreateFromDirectory(directoryToArchivePath, archiveDestinationPath);
是的,我过去用过它。 我对 DataSet 进行了一次子类化,以支持将其自身持久保存到文件中(通过 ReadXML/WriteXML 方法)。 作为额外的好处,我决定允许它根据需要进行选择性压缩(正如大家都应该知道的那样,这对于 XML 等文本数据非常有效)。
我使用了 GZipStream 类(据我当时的理解,相关的 DeflateStream 只是没有头信息的 GZip,或者类似的东西 - 我相信有人可以纠正我)。 它的工作原理非常简单,只需在另一个流的顶部搭载即可,因此您可以使用 GZipStream 代替它。 就我而言,它是搭载在 FileStream 上的。
给定一个 MemoryStream 来填充
myDataSet.WriteXML()
的输出,我做了如下操作:
if (CompressData)
{
// Write to memory
mStream = new MemoryStream();
Save(mStream);
mStream.Seek(0, SeekOrigin.Begin);
// Filter that through a GZipStream and then to file
fStream = new FileStream(Path.Combine(CacheFilePath, FileName + ".gz"),
FileMode.OpenOrCreate);
zipStream = new GZipStream(fStream, CompressionMode.Compress, true);
Pump(mStream, zipStream);
}
else
{
// Write straight to file
fStream = new FileStream(Path.Combine(CacheFilePath, FileName),
FileMode.OpenOrCreate);
Save(fStream);
}
其中
Save()
和 Pump()
是如下简单方法:
private void Pump(Stream input, Stream output)
{
int n;
byte[] bytes = new byte[4096]; // 4KiB at a time
while ((n = input.Read(bytes, 0, bytes.Length)) != 0)
{
output.Write(bytes, 0, n);
}
}
public void Save(Stream stream)
{
AcceptChanges();
WriteXml(stream, XmlWriteMode.WriteSchema);
}
public static void zIpDatabseFile(string srcPath, string destPath)
{//This is for Zip a File
using (var source = new FileStream(srcPath, FileMode.Open, FileAccess.Read, FileShare.Read))
using (var dest = new FileStream(destPath, FileMode.OpenOrCreate, FileAccess.Write))
using (var zip = new GZipStream(dest, CompressionMode.Compress))
{
source.CopyTo(zip);
}
}
public static void uNzIpDatabaseFile(string SrcPath, string DestPath)
{// This is for unzip a files.
using (var source = new FileStream(SrcPath, FileMode.Open, FileAccess.Read, FileShare.Read))
using (var dest = new FileStream(DestPath, FileMode.OpenOrCreate, FileAccess.Write))
using (var zip = new GZipStream(source, CompressionMode.Decompress))
{
zip.CopyTo(dest);
}
}