AddEntry with WriteDelegate doesn't end up writing the right size into the LocalFileHeader in the resulting zip.

Dec 21, 2013 at 10:06 PM
Edited Dec 22, 2013 at 12:51 AM
I am adding a zip file to another zip using AddEntry with a write delegate, and although many 3rd party programs can parse the resulting file, the particular app I am trying to write the zip file for cannot load the file. Debugging through the other app, it appears as though the local file header in the resulting zip has 0 for the size of the files. I can get it to work by saving the inner zip to a temp file first, but I would like to avoid that.

Here are some simplified versions of the problem I am seeing. I'm not sure if it matters, but both zip files are uncompressed.

This works:
    ZipFile output = GetOutputFile();
    IDictionary<string, ZipFile> pakFiles = GetPackFiles();

    foreach (var pakEntry in pakFiles)
    {
        var p = pakEntry.Value;
        if (p.Count > 0)
        {
            var tempStream = File.Open(Path.GetTempFileName(), FileMode.Open, FileAccess.ReadWrite);
            p.Save(tempStream);
            tempStream.Seek(0, SeekOrigin.Begin);
            output.AddEntry(pakEntry.Key, tempStream);
        }
    }

    output.Save(stream);
And this doesn't:
    ZipFile output = GetOutputFile();
    IDictionary<string, ZipFile> pakFiles = GetPackFiles();

    foreach (var pakEntry in pakFiles)
    {
        var p = pakEntry.Value;
        if (p.Count > 0)
        {
            output.AddEntry(pakEntry.Key, (string entryName, Stream s) => { p.Save(s); });
        }
    }

    output.Save(stream);
Dec 22, 2013 at 12:18 AM
To clarify, it is the local file headers in the inner zip file that are not correct.

Is it possible that ZipFile.Save uses seeking within the stream to write the file sizes after writing the entry? I believe the default stream that is used by ZipFile doesn't support seeking, so I wonder if it is just failing to seek back to update the file size in the local file header?