DotNetZip BadReadException on .Extract

Ilya Kozhevnikov picture Ilya Kozhevnikov · Mar 11, 2013 · Viewed 13.6k times · Source

I've got a weird file that when zipped with DotNetZip creates an 'ununzipable' archive. When I try to unzip it with 7zip it fails with CRC failed in 'AjaxControlToolkit.dll'. File is broken. When I zip it with 7zip manually it unzips fine.

Has anyone come across a scenario where DotNetZip fails to zip a simple binary file correctly? Or am I using DotNetZip incorrectly?

https://dl.dropbox.com/u/65419748/AjaxControlToolkit.dll

using System.IO;
using Ionic.Zip;

namespace ConsoleApplication1
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var source = new FileInfo(@"C:\ZipDemo\AjaxControlToolkit.dll");
            var target = new FileInfo(Path.ChangeExtension(source.FullName, "zip"));
            var folder = new DirectoryInfo(Path.ChangeExtension(source.FullName, null));

            if (target.Exists)
                target.Delete();

            if (folder.Exists)
                folder.Delete(true);

            using (var zip = new ZipFile(target.FullName))
            {
                zip.AddFile(source.FullName, string.Empty);
                zip.Save();
            }

            using (var zip = new ZipFile(target.FullName))
                zip.ExtractAll(folder.FullName);
        }
    }
}

Throws:

Unhandled Exception: Ionic.Zip.BadReadException: bad read of entry AjaxControlToolkit.dll from compressed archive.
   at Ionic.Zip.ZipEntry._CheckRead(Int32 nbytes)
   at Ionic.Zip.ZipEntry.ExtractOne(Stream output)
   at Ionic.Zip.ZipEntry.InternalExtract(String baseDir, Stream outstream, String password)
   at Ionic.Zip.ZipFile._InternalExtractAll(String path, Boolean overrideExtractExistingProperty)
   at Ionic.Zip.ZipFile.ExtractAll(String path)
   at ConsoleApplication1.Program.Main(String[] args) in C:\ZipDemo\ConsoleApplication1\ConsoleApplication1\Program.cs:line 27

Edit:

If I add an extra byte it works just fine, but it's not an acceptable solution. Fails without the + 1.

var bytes = new byte[source.Length + 1];
File.ReadAllBytes(source.FullName).CopyTo(bytes, 0);
zip.AddEntry(source.Name, bytes);

Update:

Gave up and switched to SharpZipLib as it doesn't blow up on simple extract, but sure would be nice to know what was wrong with DotNetZip, it has a nicer API.

Update2:

Something about the length of file makes it blow up, 1179647 and 1179649 bytes are zipped and unzipped correctly.

var source = new FileInfo(@"C:\ZipDemo\foo.txt");
using (var writer = source.CreateText())
    writer.Write(new string('a', 1179648));

Answer

Xaruth picture Xaruth · Aug 20, 2013

Size of your dll is 53*128k (6954496/131072 = 53), and there is a bug in DotNetZip as you can read there : https://dotnetzip.codeplex.com/workitem/14087. Just use in your code:

zip.ParallelDeflateThreshold = -1;

I had this problem for lot of files, it's working perfectly now ;)