SharpZipLib - ZipException «Конец дополнительных данных» - Почему я получаю это исключение? - PullRequest
0 голосов
/ 30 сентября 2008

Я использую SharpZipLib версии 0.85.5 для распаковки файлов. Мой код работал хорошо в течение нескольких месяцев, пока я не нашел ZIP-файл, который ему не нравится.

ICSharpCode.SharpZipLib.Zip.ZipException: End of extra data     
    at ICSharpCode.SharpZipLib.Zip.ZipExtraData.ReadCheck(Int32 length) in C:\C#\SharpZLib\Zip\ZipExtraData.cs:line 933     
    at ICSharpCode.SharpZipLib.Zip.ZipExtraData.Skip(Int32 amount) in C:\C#\SharpZLib\Zip\ZipExtraData.cs:line 921     
    at ICSharpCode.SharpZipLib.Zip.ZipEntry.ProcessExtraData(Boolean localHeader) in C:\C#\SharpZLib\Zip\ZipEntry.cs:line 925     
    at ICSharpCode.SharpZipLib.Zip.ZipInputStream.GetNextEntry() in C:\C#\SharpZLib\Zip\ZipInputStream.cs:line 269     
    at Constellation.Utils.Tools.UnzipFile(String sourcePath, String targetDirectory) in C:\C#\Constellation2\Utils\Tools.cs:line 90     
--- End of inner exception stack trace ---

Вот мой метод распаковки:

     public static void UnzipFile(string sourcePath, string targetDirectory)
     {
        try
        {
            using (ZipInputStream s = new ZipInputStream(File.OpenRead(sourcePath)))
            {
                ZipEntry theEntry;
                while ((theEntry = s.GetNextEntry()) != null)
                {
                    //string directoryName = Path.GetDirectoryName(theEntry.Name);
                    string fileName = Path.GetFileName(theEntry.Name);

                    if (targetDirectory.Length > 0)
                    {
                        Directory.CreateDirectory(targetDirectory);
                    }

                    if (fileName != String.Empty)
                    {
                        using (FileStream streamWriter = File.Create(targetDirectory + fileName))
                        {
                            int size = 2048;
                            byte[] data = new byte[2048];
                            while (true)
                            {
                                size = s.Read(data, 0, data.Length);
                                if (size > 0)
                                {
                                    streamWriter.Write(data, 0, size);
                                }
                                else
                                {
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
        catch (Exception ex)
        {
            throw new Exception("Error unzipping file \"" + sourcePath + "\"", ex);
        }
    }

Файл прекрасно распаковывается с помощью встроенной в XP поддержки ZIP, WinZIP и 7-Zip. Исключение выдается на s.GetNextEntry().

Ответы [ 4 ]

1 голос
/ 30 сентября 2008

Возможно, что другие zip-инструменты игнорируют лишние данные, которые повреждены, или в равной степени возможно наличие ошибки в #ZipLib. (Я нашел один недавно - определенный файл, который не будет сжиматься, а затем распаковываться чисто с определенными параметрами.)

В этом конкретном случае я предлагаю вам опубликовать на форуме #ZipLib, чтобы привлечь внимание разработчиков. Если в вашем файле нет конфиденциальных данных, и вы можете получить их вместе с короткой, но полной программой, я подозреваю, что это очень поможет.

0 голосов
/ 19 июня 2015

В соответствии с 4.5.3 из официальной спецификации ZIP , поля Size & CompressedSize дополнительных данных «ДОЛЖНЫ появляться только в том случае, если для соответствующего поля записи в локальном или центральном каталоге установлено значение 0xFFFF или 0xFFFFFFFF».

Но SharpZipLib записывает его в метод ZipFile.WriteCentralDirectoryHeader, только если "useZip64_ == UseZip64.On". Я добавил entry.IsZip64Forced() состояние и ошибка исчезает)

            if ( entry.CentralHeaderRequiresZip64 ) {
            ed.StartNewEntry();

            if ((entry.Size >= 0xffffffff) || (useZip64_ == UseZip64.On) || entry.IsZip64Forced())
            {
                ed.AddLeLong(entry.Size);
            }

            if ((entry.CompressedSize >= 0xffffffff) || (useZip64_ == UseZip64.On) || entry.IsZip64Forced())
            {
                ed.AddLeLong(entry.CompressedSize);
            }
0 голосов
/ 01 октября 2008

См. официальную спецификацию ZIP .

Каждый файл в ZIP-архиве может иметь дополнительное поле, связанное с ним. Я думаю, #ZipLib говорит вам, что заданная «дополнительная» длина поля была больше, чем объем данных, которые были доступны для чтения; другими словами, файл ZIP, скорее всего, был усечен.

0 голосов
/ 01 октября 2008

Я согласен с Джоном. Не удалось разместить следующее в комментарии:

(хотя это не отвечает на ваш вопрос) Разве не проще использовать что-то вроде этого:

public static void UnzipFile(string sourcePath, string targetDirectory)
{
    try
    {
        FastZip fastZip = new FastZip();
        fastZip.CreateEmptyDirectories = false;
        fastZip.ExtractZip(sourcePath, targetDirectory,"");
    }
    catch(Exception ex)
    {
        throw new Exception("Error unzipping file \"" + sourcePath + "\"", ex);
    }
}
...