Search code examples
c#zipchecksumdotnetzip

DotNetZip Creates corrupt archives (bad CRC)


There's a strange problem with DotNetZip that I can't seem to find a solution to. I've searched for a few hours now and I just can't find anything on this, so here goes.

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

I need to add the modified time, which is rather crucial, but right now I just have a dummy timestamp.

When I open the file with WinRAR, it says "Unexpected end of archive". Each individual file has checksum 00000000, and WinRAR says "The archive is either in unknown format or damaged". I can repair it, which brings it down 20% in size and makes everything OK. But that's not really useful..

When I make a breakpoint after adding all the entries, I can see in zip.Entries that all the entries have that same bad CRC, but all the data seems to be there. So it shouldn't be the way I save the archive that's the problem.

I use my file collection elsewhere without problems, which adds to DotNetZip being weird. Well either that or I misunderstand something :)


Solution

  • GetBuffer is certainly wrong. It returns the internal buffer of the MemoryStream, which is often bigger than the actual content.

    To return an array that only contains the actual content, use ToArray().

    Or you could carefully handle the incompletely filled buffer in the consuming code. This would reduce GC pressure, since you don't need to allocate a whole new array for the return value.

    If the zip-archive is large, I'd also consider saving to a file directly, instead of assembling the archive in-memory.