I have a strange problem when creating a new Zip archive using SharpZipLib. I can create the Zip file successfully and it can be read fine by various Zip utilities, but when extracting the file contained within, I get an error resembling the following:
-
'The compressed size stored in the local header for this file is not the same as the compressed size stored in the central directory header.'
Using a Hex editor, I can see that indeed the Central directory header has a compressed size of 64 bytes (correct) for my file, but the local header is FFFF which is incorrect. I have debugged my code and have found that the CompressedSize of the ZipEntry object gets set when you call ZipOutputStream.Finish() but the data in the stream does not get updated with this value - presumably because it was written to the stream before the compressedsize was available. Short of manually searching the stream and updating the value with the value ripped from the Central directory header, which is a bit hacky, I'm out of ideas. If anyone can spot anything obvious I'm doing wrong, it would be very much appreciated.
My code is as follows:
// get the data and store in unzipped byte array
Byte[ unzippedData = encoding.GetBytes(data);
// create CRC for unzipped data
Crc32 crc = new Crc32();
crc.Reset();
crc.Update(unzippedData);
// create memory stream to hold zipped data
MemoryStream zippedStream = new MemoryStream();
ZipOutputStream zipOut = new ZipOutputStream(zippedStream);
ZipEntry zipEntry = new ZipEntry(ConfigurationManager.AppSettings["CSVName"]);
zipEntry.CompressionMethod = CompressionMethod.Deflated;
zipEntry.Size = unzippedData.Length;
zipEntry.Crc = crc.Value;
zipEntry.ZipFileIndex = 1;
zipEntry.DateTime = DateTime.Now;
// write header for our csv file
zipOut.PutNextEntry(zipEntry);
// write the file data
zipOut.Write(unzippedData, 0, unzippedData.Length);
// ** ONLY AFTER THIS POINT DOES THE COMPRESSEDSIZE GET SET IN ZIPENTRY
zipOut.Finish();
zipOut.Flush();
// insert the NHS string at beginning of data, before header
IEnumerable<Byte> zippedData = zippedStream.ToArray();
IEnumerable<Byte> nhsString = encoding.GetBytes(_NHSZipString);
zippedData = nhsString.Concat(zippedData);
// clean up
zipOut.Close();
// return as array of bytes
return zippedData.ToArray();
Many thanks
Dan
Answer
Just a quick follow up. This problem seems to be resolved if I don't set the CRC for the ZipEntry - the local header has the expected value and the file extracts successfully in multiple Zip applications. This ring any bells with anyone?