Como lidar com a descompactação do ZipFile com caminhos muito longos/duplicados

StackOverflow https://stackoverflow.com//questions/10677405

  •  12-12-2019
  •  | 
  •  

Pergunta

Ao descompactar arquivos no Windows, ocasionalmente terei problemas com caminhos

  1. que são muito longos para o Windows (mas são adequados no sistema operacional original que criou o arquivo).
  2. que são "duplicados" devido à insensibilidade a maiúsculas e minúsculas

Usando DotNetZip, o ZipFile.Read(path) call irá falhar sempre que ler arquivos zip com um desses problemas.O que significa que não posso nem tentar filtrá-lo.

using (ZipFile zip = ZipFile.Read(path))
{
    ...
}

Qual é a melhor maneira de ler esse tipo de arquivo?

Atualizada:

Exemplo zip daqui:https://github.com/MonoReports/MonoReports/zipball/master

Duplicatas:https://github.com/MonoReports/MonoReports/tree/master/src/MonoReports.Model/DataSourceType.cshttps://github.com/MonoReports/MonoReports/tree/master/src/MonoReports.Model/DatasourceType.cs

Aqui estão mais detalhes sobre a exceção:

Ionic.Zip.ZipException:Não é possível ler isso como um ZipFile
---> System.ArgumentException:Um item > com a mesma chave já foi adicionado.
em System.ThrowHelper.ThrowArgumentException (recurso ExceptionResource)
em System.Collections.Generic.Dictionary2.Insert(TKey key, TValue value, Boolean add)
at System.Collections.Generic.Dictionary
2.Adicionar (chave TKey, valor TValue)
em Ionic.Zip.ZipFile.ReadCentralDirectory(ZipFile zf)
em Ionic.Zip.ZipFile.ReadIntoInstance(ZipFile zf)

Resolução:

Com base na sugestão do @Cheeso, posso ler tudo do stream, evitando duplicatas e problemas de caminho:

//using (ZipFile zip = ZipFile.Read(path))
using (ZipInputStream stream = new ZipInputStream(path))
{
    ZipEntry e;
    while( (e = stream.GetNextEntry()) != null )
    //foreach( ZipEntry e in zip)
    {
        if (e.FileName.ToLower().EndsWith(".cs") ||
            e.FileName.ToLower().EndsWith(".xaml"))
        {
            //var ms = new MemoryStream();
            //e.Extract(ms);
            var sr = new StreamReader(stream);
            {
                //ms.Position = 0;
                CodeFiles.Add(new CodeFile() { Content = sr.ReadToEnd(), FileName = e.FileName });
            }
        }
    }
}
Foi útil?

Solução

Leia com ZipInputStream.

A classe ZipFile mantém uma coleção usando o nome do arquivo como índice.Nomes de arquivos duplicados quebram esse modelo.

Mas você pode usar o ZipInputStream para ler seu arquivo zip.Não há coleção ou índice nesse caso.

Outras dicas

Para o PathTooLongException problema, descobri que você não pode usar DotNetZip.Em vez disso, o que fiz foi invocar o versão de linha de comando do 7-zip;isso faz maravilhas.

public static void Extract(string zipPath, string extractPath)
{
    try
    {
        ProcessStartInfo processStartInfo = new ProcessStartInfo
        {
            WindowStyle = ProcessWindowStyle.Hidden,
            FileName = Path.GetFullPath(@"7za.exe"),
            Arguments = "x \"" + zipPath + "\" -o\"" + extractPath + "\""
        };
        Process process = Process.Start(processStartInfo);
        process.WaitForExit();
        if (process.ExitCode != 0) 
        {
            Console.WriteLine("Error extracting {0}.", extractPath);
        }
    }
    catch (Exception e)
    {
        Console.WriteLine("Error extracting {0}: {1}", extractPath, e.Message);
        throw;
    }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top