Как справиться с распаковкой ZipFile со слишком длинными/дублирующими путями

При распаковке файлов в Windows у меня иногда возникают проблемы с путями

  1. это слишком долго для Windows (но нормально в оригинальной ОС, которая создала файл).
  2. которые являются «дубликатами» из-за нечувствительности к регистру

При использовании DotNetZip вызов ZipFile.Read(path) будет прерываться при чтении zip-файлов с одной из этих проблем. А это значит, что я даже не могу попытаться его отфильтровать.

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

Каков наилучший способ справиться с чтением таких файлов?

Обновлено:

Пример zip отсюда: https://github.com/MonoReports/MonoReports/zipball/master

Дубликаты: https://github.com/MonoReports/MonoReports/tree/master/src/MonoReports.Model/DataSourceType.cs https://github.com/MonoReports/MonoReports/tree/master/src/MonoReports.Model/DatasourceType.cs

Вот более подробная информация об исключении:

Ionic.Zip.ZipException: невозможно прочитать это как ZipFile
---> System.ArgumentException: > элемент с таким же ключом уже добавлен.
в System.ThrowHelper.ThrowArgumentException(ресурс ExceptionResource)
в System.Collections.Generic.Dictionary2.Insert(TKey key, TValue value, Boolean add)
at System.Collections.Generic.Dictionary
2.Add(ключ TKey, значение TValue)
в Ionic.Zip.ZipFile.ReadCentralDirectory(ZipFile zf)
в Ionic.Zip.ZipFile.ReadIntoInstance(ZipFile zf)

Решение:

Основываясь на предложении @Cheeso, я могу прочитать все из потока, избегая дубликатов и проблем с путями:

//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 });
            }
        }
    }
}

person gameweld    schedule 20.05.2012    source источник
comment
Это файл .zip или .gz?   -  person SimpleVar    schedule 21.05.2012
comment
.zip (в частности, из загрузок zip-файлов github)   -  person gameweld    schedule 21.05.2012
comment
Можете показать ошибку? Это путь внутри файла? Это слишком длинное расположение целевого файла?   -  person yamen    schedule 21.05.2012
comment
Я обновил вопрос, чтобы он был более общим: как повторяющиеся файлы, так и длинные пути являются проблемой и включают примеры.   -  person gameweld    schedule 22.05.2012


Ответы (2)


Прочтите вместе с ZipInputStream.

Класс ZipFile хранит коллекцию, используя имя файла в качестве индекса. Повторяющиеся имена файлов нарушают эту модель.

Но вы можете использовать ZipInputStream для чтения в ZipFile. В этом случае нет коллекции или индекса.

person Cheeso    schedule 27.05.2012

Что касается проблемы PathTooLongException, я обнаружил, что вы не можете использовать DotNetZip. Вместо этого я вызвал версию командной строки 7-zip. ; что творит чудеса.

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;
    }
}
person Maria Ines Parnisari    schedule 05.02.2015
comment
На самом деле это самое простое решение, которое я нашел. Во время этого комментария может быть полезно знать, что 7za.exe находится в загрузках 7-zip с дополнительным 7-zip: .... в описании. (7-zip.org/download.html) - person Dave Welling; 08.02.2015
comment
Строка Arguments неверна; это должно быть Arguments = "x \"" + zipPath + "\" -o \"" + extractPath + "\"" (обратите внимание на отсутствие пробела между переключателем o и extractPath. - person sigil; 27.12.2016
comment
Спасибо @sigil, в соответствии с этим вы правы, я обновил свой отвечать. - person Maria Ines Parnisari; 27.12.2016
comment
Хороший ответ. Также, чтобы избежать остановки процесса с подсказкой о переопределении существующих, вы можете добавить -y к аргументам - person RVid; 16.03.2017