Имя записи ZIP заканчивается символом разделителя каталогов, но содержит данные

System.IO.Compression.ZipFile.ExtractToDirectory(zipPath, extractPath);

Используя ZipFile в С#, я пытаюсь извлечь файл из известного места, и он выдает следующую ошибку: System.IO.Exception: имя записи Zip заканчивается символом разделителя каталогов, но содержит данные

Я провел некоторое исследование, ExtractToDirectory объясняется в MSDN, но не смог найти это определение ошибки. Не могли бы вы объяснить, почему возникает эта ошибка?

Из MSDN:

IOException

Каталог, указанный в параметре destinationDirectoryName, уже существует.

-or-

Имя записи в архиве пусто, содержит только пробел или хотя бы один недопустимый символ.

-or-

При извлечении записи из архива будет создан файл, находящийся за пределами каталога, указанного в параметре destinationDirectoryName. (Например, это может произойти, если имя записи содержит средства доступа к родительскому каталогу.)

-or-

Архивная запись, которую нужно извлечь, имеет то же имя, что и запись, которая уже была извлечена из того же архива.


person erenalgan    schedule 24.07.2014    source источник
comment
Я предполагаю, что это означает, что имя файла, хранящегося в zip-архиве, либо содержит .., либо заканчивается на ``. Вы уверены, что не испортите пути, например. используя целевой путь в качестве внутреннего пути zip-архива?   -  person Mario    schedule 24.07.2014
comment
Одна вещь, которую я обнаружил, потратив пару часов, заключается в том, что эта проблема связана со способом создания zip-файла. Чтобы проблема возникла, я сгенерировал zip-файл с помощью 7-zip. Создание zip-файла с помощью WinRar решило проблему. Хотя я до сих пор не знаю первопричины этого.   -  person erenalgan    schedule 25.07.2014
comment
@Марио, это было и мое первоначальное предположение. Однако я не нашел никаких проблем с путями (хотя спасибо за комментарий).   -  person erenalgan    schedule 25.07.2014


Ответы (3)


Мое исследование показывает, что когда вы сжимаете файлы с помощью утилиты 7-Zip с использованием уровня сжатия «Ультра», некоторые архивы не могут быть распакованы с помощью метода .NET System.IO.Compression.ZipFile.ExtractToDirectory(). Сообщение об ошибке: Имя записи ZIP заканчивается символом разделителя каталогов, но содержит данные.

По моим наблюдениям, эта ошибка возникает только при соблюдении следующих 3 условий:

  1. Целевой архив большой - 500 МБ+ (маленькие архивы, похоже, нормально распаковываются).
  2. В корне архива ТОЛЬКО ПАПКИ (если добавить хоть один файл в корень архива он тоже нормально разархивируется).
  3. Используется сжатие 7-Zip Ultra.

В конце концов я нашел три решения этой ошибки 7-Zip.

Решение 1. Добавьте хотя бы один файл в корень архива (любой фиктивный файл или файл readme.txt).

Решение 2. Используйте встроенную утилиту сжатия Windows (выберите файлы, щелкните правой кнопкой мыши, «Отправить» -> «Сжатая папка»).

Решение 3. Не используйте сжатие 7-Zip Ultra.

Все эти решения решили проблему для меня. Выберите тот, который лучше всего подходит для вашего проекта.

person Alex X.    schedule 31.03.2015
comment
Еще одно возможное условие, которое я обнаружил, - если вы используете 7zip для сжатия чего-то, что находится на смонтированном диске (но родном для OSX). У меня есть виртуальная машина, на которой я работаю в Windows, но диск используется совместно двумя ОС. Решение 2 устранило эту конкретную проблему. - person JasCav; 26.08.2015
comment
У меня есть файл .zip, созданный с помощью 7z, с использованием параметра -tzip, который эквивалентен -tzip -mm=Deflate -mx=5, т. е. он не использует ультрасжатие 7-zip. Также я поместил файл в стопку архива. Файл большой, более 600 МБ, содержащий 45000 файлов в 36 каталогах. Я открыл zip-файл с помощью System.IO.Compression.ZipFile.Open в отладчике. Среди всех 36 записей dirs все заканчиваются символом /, но только две имеют ненулевую длину, и эта длина совершенно бессмысленна. В результате System.IO.Compression.ZipFile не может распаковать файл, т.е. soln 1 и 3 не работают. - person David I. McIntosh; 16.03.2017

Ошибка возникает, когда запись ZipArchive заканчивается символом разделителя каталогов '/', но имеет длину != 0

Вы можете легко найти эти записи с помощью

zip.Entries.Where(o => o.FullName.EndsWith("/") && o.Length != 0)
person MerickOWA    schedule 05.05.2016
comment
Спасибо за это. У меня возникает вопрос, откуда берется эта ненулевая длина? Все каталоги в zip-архиве заканчиваются на /, но все должны иметь длину 0. Очень редко некоторые не имеют нулевой длины, и в этих случаях длина кажется совершенно бессмысленной. Есть ли у вас какие-либо идеи, заключается ли ошибка в архиве, который создает 7z.exe, или ошибка заключается в System.IO.Compression.ZipFile.Open ?? - person David I. McIntosh; 17.03.2017
comment
@DavidI.McIntosh Я не могу представить, что ZipFile.Open каким-то образом изменяет содержимое zip. Гораздо более вероятно, что это вызвано внешней программой zip, которая вызывает это. Это должно быть легко проверить, сделав копию zip-файла до ZipFile.Open и сравнив оригинал с открытым файлом, чтобы убедиться, что он не был изменен. - person MerickOWA; 17.03.2017
comment
Извините, я не ясно выразился. Если вина лежит на System.IO.Compression.ZipFile.Open, я не задавался вопросом, изменяет ли он файл .zip. Мы видим ненулевую длину в структуре данных, которую System.IO.Compression.ZipFile.Open строит при чтении в zip-файле, но мне не ясно, действительно ли это неверные данные в файле, или System.IO.Compression.ZipFile.Open имеет ошибку, из-за которой он построить внутреннюю структуру данных с неправильной записью длины. - person David I. McIntosh; 28.07.2017
comment
@DavidI.McIntosh Единственный раз, когда я видел проблему, это было из-за плохих файлов. Я не видел никаких проблем с обработкой данных в .NET. Формат zip-файла не так уж плох для идентификации заголовков файлов и проверки длины, отличной от нуля, с помощью двоичного редактора. - person MerickOWA; 28.07.2017

Я борюсь с этой проблемой, и даже некоторые пакеты, такие как SharpZip, не работают. (проблема появляется в TeamCity и zip-архиве артефакта)

Завершите это решение с помощью SharpCompress(https://www.nuget.org/packages/sharpcompress/)

var archive = ArchiveFactory.Open(model.UserParams.PathToZipFile.FullName);

foreach (var entry in archive.Entries)
{
  if (entry.IsDirectory == false)
  {
   entry.WriteToDirectory(unZipDirectory, new ExtractionOptions() { ExtractFullPath = true, Overwrite = true });
  }
}
person blogprogramisty.net    schedule 09.04.2021