2012-04-24 5 views
4

Есть странная проблема с DotNetZip, что я не могу найти решение. Я искал несколько часов, и я просто ничего не могу найти по этому поводу, так что здесь.DotNetZip Создает поврежденные архивы (плохой CRC)

var ms = new MemoryStream(); 
using (var archive = new Ionic.Zip.ZipFile()) { 
    foreach (var file in files) { 
     //        string  byte[] 
     var entry = archive.AddEntry(file.Name, file.Data); 
     entry.ModifiedTime = DateTime.Now.AddYears(10); // Just for testing 
    } 
    archive.Save(ms); 
} 
return ms.GetBuffer(); 

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

Когда я открываю файл с помощью WinRAR, он говорит «Неожиданный конец архива». Каждый отдельный файл имеет контрольную сумму 00000000, а WinRAR говорит: «Архив находится в неизвестном формате или поврежден». Я могу отремонтировать его, что снижает его на 20% и делает все в порядке. Но это не очень полезно.

Когда я делаю точку останова после добавления всех записей, я вижу в zip.Entries, что все записи имеют тот же самый плохой CRC, но все данные, кажется, есть. Так что это не должно быть так, как я сохраняю архив, это проблема.

Я использую свою коллекцию файлов в других местах без проблем, что добавляет, что DotNetZip является странным. Ну или это или я неправильно понимаю что-то :)

+2

'GetBuffer', безусловно, неверен, поскольку буфер часто больше, чем содержимое. Используйте 'ToArray()'. Или тщательно обрабатывайте незаполненный буфер в коде потребления. – CodesInChaos

+0

Я рад, что мы ушли с дороги. Это фактически решило проблему. Можете ли вы добавить этот комментарий в качестве ответа, чтобы я мог принять его как таковой? – Heki

ответ

6

GetBuffer, безусловно, неправильно. Он возвращает внутренний буфер MemoryStream, который часто больше, чем фактический контент.

Чтобы вернуть массив, содержащий только фактический контент, используйте ToArray().

Или вы могли бы тщательно обработать незаполненный буфер в коде потребления. Это уменьшило бы давление GC, поскольку вам не нужно выделять целый новый массив для возвращаемого значения.

Если zip-архив большой, я бы также подумал о сохранении файла напрямую, вместо того, чтобы собирать архив в памяти.

+0

Спасибо, CodeInChaos. Здесь у вас есть хорошие моменты. Обработка буфера будет заключаться в том, чтобы удалить все конечные 0 байтов? – Heki

+1

Это зависит от кода вызова. Это будет означать прохождение по длине действительных данных и соответствующее лечение. Вы не можете считать все завершающие байты '0' недействительными, только те, которые превышают' ms.Length'. – CodesInChaos