CompressedSize in local header does not match that of central directory header in new zip file
2010-03-18 18:39
525 查看
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?
'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?
相关文章推荐
- Unity3d 提示 "The scripts file name does not match the name of the class defined in the script!"的解决办法
- The idcode read from the device does not match the idcode in the bsdl File.
- vmware-tool 安装缺少头文件 What is the location of the directory of C header files that match your running
- Reference in the manifest does not match the identity of the downloaded assembly
- wmware提示What is the location of the directory of C header files that match your running kernel?
- Get and display the size of file and directory in Linux system using du command 获取和现实linux文件大小(三)
- what is the location of the directory of c header files that match your running kernel -SLES11.2
- iOS-This application’s application-identifier entitlement does not match that of the installed appl
- What is the location of the directory of C header files that match your running kernel?
- iOS-This application’s application-identifier entitlement does not match that of the installed appli
- This application's application-identifier entitlement does not match that of the installed applicati
- 【iOS开发】This application's application-identifier entitlement does not match that of the installed ap
- 终于解决了问题What is the location of the directory of C header files that match your running kernel
- s signer information does not match signer information of other classes in the same packag
- The value of CFBundleShortVersionString in your WatchKit app's Info.plist (1.0) does not match
- This application's application-identifier entitlement does not match that of the installed applicati
- poi 3.2 SecurityException HPSFException signer information does not match signer information of other classes in the same package
- VMware虚拟机ubuntu和主操作系统硬盘之间的文件共享的实现和What is the location of the directory of C header files that match your running问题的解决办法
- 上传时报错:The Bundle ID xxx defined in your Xcode Project does not match the Bundle ID that you
- What is the location of the directory of C header files that match