如何从 zip 文件中读取数据而无需解压缩整个文件

Posted

技术标签:

【中文标题】如何从 zip 文件中读取数据而无需解压缩整个文件【英文标题】:How to read data from a zip file without having to unzip the entire file 【发布时间】:2011-08-23 11:55:14 【问题描述】:

.Net (C#) 中是否有从 zip 文件中提取数据而不解压缩完整文件的方法?

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

【问题讨论】:

欺骗***.com/questions/328343/… ? 但是另一个线程是 12 岁。也许过时了? 【参考方案1】:

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

在 zipfile 中找到“myfile”并解压。

【讨论】:

也可以使用 entry.Open() 来获取流(如果内容应该被读取但不写入文件)。 参考:System.IO.Compression.dllSystem.IO.Compression.FileSystem.dll【参考方案2】:

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("\n1,-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 已关闭。旧档案仍然是available at Codeplex。看起来代码已经迁移到Github了:

https://github.com/DinoChiesa/DotNetZip。貌似是原作者的repo。 https://github.com/haf/DotNetZip.Semverd。这看起来是当前维护的版本。它还通过 Nuget 打包,地址为https://www.nuget.org/packages/DotNetZip/

【讨论】:

+1。在幕后,DotNetZip 在构造函数中所做的是寻找 zip 文件中的“目录”,然后读取它并填充条目列表。此时,如果您的应用程序在一个条目上调用 Extract(),DotNetZip 会寻找 zip 文件中的适当位置,并仅为该条目解压缩数据。【参考方案3】:

如果你想使用 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

【讨论】:

坦率地说,我看不出这个链接是如何回答这个问题的。【参考方案4】:

以下是如何将 UTF8 文本文件从 zip 存档读取到字符串变量(.NET Framework 4.5 及更高版本):

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

【讨论】:

【参考方案5】:

Zip 文件有一个目录。每个 zip 实用程序都应该能够仅查询 TOC。或者您可以使用 7zip -t 之类的命令行程序打印目录并将其重定向到文本文件。

【讨论】:

【参考方案6】:

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

【讨论】:

【参考方案7】:

以下代码可以将特定文件读取为字节数组:

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

【讨论】:

以上是关于如何从 zip 文件中读取数据而无需解压缩整个文件的主要内容,如果未能解决你的问题,请参考以下文章

在python中读取csv压缩文件

如何使用Windows的内置功能从脚本中压缩或解压缩?

解压缩文件将文件转换为字节

是否可以直接从存储在 S3 上的 zip 文件中读取特定文件?

获取Zip文件中文件的解压缩流

访问 .zip 存档中的文件而不提取它们