21

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));
Ilya Kozhevnikov
  • 10,242
  • 4
  • 40
  • 70

3 Answers3

17

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

Xaruth
  • 4,034
  • 3
  • 19
  • 26
  • This solves the same issue in C#4.5 File Compression method too :) – Palanikumar Jun 09 '15 at 13:35
  • 1
    Thanks! This is the easy solution and sufficient for me. Compiling in the fix suggested by @laktak below is probably the better option, but probably unnecessary unless you really need the optimization of parallel deflate. It's a shame that the official code repo seems to have been inactive since 2011 - not sure if there's a newer more active one that's continued to update or not. – Chaser324 Jan 10 '17 at 21:24
  • It seems that the link no longer takes you directly to the work item that is referenced in this issue. So if you are interested in finding the work item you can click the link, switch to the "issues" tab, and search "ZipFile.AddFile fails depending of the file size." on the page. That issue looks like it is the work item 14087. – Ben.12 Sep 10 '19 at 14:11
4

It's a bug - you can fix it in Zlib\ParallelDeflateOutputStream.cs.

change

} while (doAll && (_lastWritten != _latestCompressed));

to

} while (doAll && (_lastWritten != _lastFilled)); 

See https://dotnetzip.codeplex.com/workitem/14087 for more info.

laktak
  • 57,064
  • 17
  • 134
  • 164
2

I tried this -

  • Install Latest version of DotNetZip
  • Run your code.
  • Got the BadReadException

Then this -

  • Install an older version (1.9) of DotNetZip. (Install-Package DotNetZip -Version 1.9)
  • Run your code
  • Code works fine.

I guess this could be a bug?

Srikanth Venugopalan
  • 9,011
  • 3
  • 36
  • 76
  • Looks like it, submitted a bug http://dotnetzip.codeplex.com/workitem/16092 can't tell if there are others like it, seems like CodePlex itself is borked and doesn't display workitem descriptions. – Ilya Kozhevnikov Mar 11 '13 at 12:58
  • 1
    Cool. Have updated your bug with the sample that I could get working, should be useful for anyone troubleshooting. – Srikanth Venugopalan Mar 11 '13 at 13:00
  • that's not the solution ! As you change version, size is changing, so you don't see the problem ... for now. But next update, problem can accurs again ! – Xaruth Aug 20 '13 at 15:38
  • @Xaruth, not sure I understand your point. All I did was add a file to archive, extract and compare it with the original. It threw an exception. Ref [this issue](https://dotnetzip.codeplex.com/workitem/14087) for some analysis on these lines. – Srikanth Venugopalan Aug 20 '13 at 15:57