Como ler dados de um arquivo zip sem ter que descompactar todo o arquivo

97

Existe alguma maneira em .Net (C #) para extrair dados de um arquivo zip sem descompactar o arquivo completo?

Simplesmente, possivelmente, desejo extrair dados (arquivo) do início de um arquivo zip, obviamente isso depende se o algoritmo de compactação compactar o arquivo em uma ordem determinística.

AwkwardCoder
fonte

Respostas:

78

DotNetZip é seu amigo aqui.

Tão fácil quanto:

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

(você também pode extrair para um arquivo ou outros destinos).

Ler o índice do arquivo zip é tão fácil quanto:

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

  }
}

Editado para Nota: DotNetZip costumava morar no Codeplex. Codeplex foi encerrado. O arquivo antigo ainda está disponível no Codeplex . Parece que o código migrou para o Github:


Nicholas Carey
fonte
9
+1. Nos bastidores, o que DotNetZip faz no construtor é buscar o "diretório" dentro do arquivo zip, e então lê-lo e preencher a lista de entradas. Nesse ponto, se seu aplicativo chamar Extract () em uma entrada, o DotNetZip buscará o local adequado no arquivo zip e descompactará os dados apenas para essa entrada.
Cheeso de
114

Com .Net Framework 4.5 (usando ZipArchive ):

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

Encontre "myfile" em zipfile e extraia-o.

Sinatr
fonte
34
Também é possível usar entry.Open () apenas para obter o fluxo (se o conteúdo deve ser lido, mas não escrito em um arquivo).
anre
17
referências: System.IO.Compression.dlleSystem.IO.Compression.FileSystem.dll
yzorg
18

Algo assim irá listar e extrair os arquivos um por um, se você quiser usar o 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());
     }
 }

Com base neste exemplo: conteúdo dentro do arquivo zip

Javi
fonte
1
Falando francamente, não consegui ver como esse link responde à pergunta.
Callback de Eugene Mayevski
10

Veja como um arquivo de texto UTF8 pode ser lido de um arquivo zip em uma variável de string (.NET Framework 4.5 e superior):

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());
ShamilS
fonte
0

Os arquivos Zip possuem um índice. Cada utilitário zip deve ter a capacidade de consultar apenas o TOC. Ou você pode usar um programa de linha de comando como 7zip -t para imprimir o índice e redirecioná-lo para um arquivo de texto.

umilmi81
fonte
0

Nesse caso, você precisará analisar as entradas do cabeçalho local zip. Cada arquivo, armazenado em um arquivo zip, tem uma entrada de Cabeçalho de Arquivo Local anterior, que (normalmente) contém informações suficientes para descompactação. Geralmente, você pode fazer uma análise simples de tais entradas no fluxo, selecionar o arquivo necessário, copiar o cabeçalho + dados do arquivo compactado para outro arquivo e chame unzip nessa parte (se você não quiser lidar com todo o código de descompressão Zip ou biblioteca).

Nickolay Olshevsky
fonte