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

本文关键字:文件 解压缩 数据 zip 读取 | 更新日期: 2023-09-27 17:56:23

.Net (C#) 中是否有任何方法可以从 zip 文件中提取数据而无需解压缩整个文件?

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

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

使用 .

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"并将其解压缩。

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 上可用。看起来代码已迁移到 Github:

  • https://github.com/DinoChiesa/DotNetZip。看起来是原作者的存储库。
  • https://github.com/haf/DotNetZip.Semverd。这似乎是当前维护的版本。它还打包了一个可通过Nuget在 https://www.nuget.org/packages/DotNetZip/

如果你想使用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());
     }
 }

基于此示例:zip 文件中的内容

下面介绍如何将 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());

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

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 文件有一个目录。 每个 zip 实用程序都应该能够仅查询目录。 或者,您可以使用命令行程序(如 7zip -t)打印目录并将其重定向到文本文件。

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