如何在不必解压整个文件的情况下从zip文件中读取数据

119

.Net(C#)中是否有一种方法可以在不完全解压缩文件的情况下从zip文件中提取数据?

如果使用的压缩算法具有确定性顺序,我可能希望从zip文件的开头提取数据(文件)。


重复的问题 https://dev59.com/rnRC5IYBdhLWcg3wVvjL 的副本? - Magnus
2
但是那个线程已经12年了。也许已经过时了? - Bob Denny
7个回答

150

使用.Net Framework 4.5(使用ZipArchive):

using (ZipArchive zip = ZipFile.Open(zipfile, ZipArchiveMode.Read))
    foreach (ZipArchiveEntry entry in zip.Entries)
        if(entry.Name == "myfile")
            entry.ExtractToFile("myfile");

在压缩文件中查找“myfile”,并将其解压缩。


44
可以使用 entry.Open() 来获取流(如果只需要读取内容但不写入文件)。 - anre
22
参考文献:System.IO.Compression.dllSystem.IO.Compression.FileSystem.dll - yzorg
有没有办法使用这个来获取压缩文件中的精确文件路径? - Cullub
1
@Cullub,请查看entry.FullName - Sinatr

87

DotNetZip在这里可以派上用场。

非常简单:

using (ZipFile zip = ZipFile.Read(ExistingZipFile))
{
  ZipEntry e = zip["MyReport.doc"];
  e.Extract(OutputStream);
}

你也可以将其提取到文件或其他目标中。

读取zip文件的目录表格非常简单:

using (ZipFile zip = ZipFile.Read(ExistingZipFile))
{
  foreach (ZipEntry e in zip)
  {
    if (header)
    {
      System.Console.WriteLine("Zipfile: {0}", zip.Name);
      if ((zip.Comment != null) && (zip.Comment != "")) 
        System.Console.WriteLine("Comment: {0}", zip.Comment);
      System.Console.WriteLine("\n{1,-22} {2,8}  {3,5}   {4,8}  {5,3} {0}",
                               "Filename", "Modified", "Size", "Ratio", "Packed", "pw?");
      System.Console.WriteLine(new System.String('-', 72));
      header = false;
    }
    System.Console.WriteLine("{1,-22} {2,8} {3,5:F0}%   {4,8}  {5,3} {0}",
                             e.FileName,
                             e.LastModified.ToString("yyyy-MM-dd HH:mm:ss"),
                             e.UncompressedSize,
                             e.CompressionRatio,
                             e.CompressedSize,
                             (e.UsesEncryption) ? "Y" : "N");

  }
}

编辑说明: DotNetZip曾经在Codeplex上运行。Codeplex已经关闭。旧档案仍然可以在Codeplex上获得。代码貌似已迁移到Github:


12
在幕后,DotNetZip 在构造函数中所做的是寻找压缩文件中的“目录”,然后读取并填充条目列表。此时,如果您的应用程序调用了一个条目上的Extract()方法,DotNetZip就会定位到压缩文件中正确的位置,并仅解压缩那个条目的数据。 - Cheeso

20

如果你想使用SharpZipLib,可以尝试以下类似的方法逐一列出并提取文件:

var zip = new ZipInputStream(File.OpenRead(@"C:\Users\Javi\Desktop\myzip.zip"));
var filestream = new FileStream(@"C:\Users\Javi\Desktop\myzip.zip", FileMode.Open, FileAccess.Read);
ZipFile zipfile = new ZipFile(filestream);
ZipEntry item;
while ((item = zip.GetNextEntry()) != null)
{
     Console.WriteLine(item.Name);
     using (StreamReader s = new StreamReader(zipfile.GetInputStream(item)))
     {
      // stream with the file
          Console.WriteLine(s.ReadToEnd());
     }
 }

根据这个示例:content inside zip file


1
坦率地说,我看不出这个链接如何回答问题。 - Eugene Mayevski 'Callback

17
在.NET Framework 4.5及以上版本中,以下是如何从zip归档文件中读取UTF8文本文件到字符串变量的方法:
string zipFileFullPath = "{{TypeYourZipFileFullPathHere}}";
string targetFileName = "{{TypeYourTargetFileNameHere}}";
string text = new string(
            (new System.IO.StreamReader(
             System.IO.Compression.ZipFile.OpenRead(zipFileFullPath)
             .Entries.Where(x => x.Name.Equals(targetFileName,
                                          StringComparison.InvariantCulture))
             .FirstOrDefault()
             .Open(), Encoding.UTF8)
             .ReadToEnd())
             .ToArray());

4
以下代码可以将特定文件读取为字节数组:
using ZipArchive zipArchive = ZipFile.OpenRead(zipFilePath);
        foreach(ZipArchiveEntry zipArchiveEntry in zipArchive.Entries)
        {
            if(zipArchiveEntry.Name.Equals(fileName,StringComparison.OrdinalIgnoreCase))
            {
                Stream stream = zipArchiveEntry.Open();
                using MemoryStream memoryStream = new MemoryStream();
                await stream.CopyToAsync(memoryStream);
                return memoryStream.ToArray();
            }
        }

0

Zip文件有目录表。每个zip工具都应该能够查询目录表。或者您可以使用像7zip -t这样的命令行程序打印目录表并将其重定向到文本文件。


0
在这种情况下,您需要解析zip本地头条目。存储在zip文件中的每个文件都有先前的本地文件头条目,其中(通常)包含足够的信息进行解压缩。通常,您可以在流中对这些条目进行简单的解析,选择所需的文件,将头部+压缩文件数据复制到其他文件中,并在该部分上调用unzip(如果您不想处理整个Zip解压缩代码或库)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接