0
votes

I'm using SharpZipLib version 0.85.5 to unzip files. My code has been working nicely for a couple of months until I found a ZIP file that it doesn't like.

ICSharpCode.SharpZipLib.Zip.ZipException: End of extra data     
    at ICSharpCode.SharpZipLib.Zip.ZipExtraData.ReadCheck(Int32 length) in C:\C#\SharpZLib\Zip\ZipExtraData.cs:line 933     
    at ICSharpCode.SharpZipLib.Zip.ZipExtraData.Skip(Int32 amount) in C:\C#\SharpZLib\Zip\ZipExtraData.cs:line 921     
    at ICSharpCode.SharpZipLib.Zip.ZipEntry.ProcessExtraData(Boolean localHeader) in C:\C#\SharpZLib\Zip\ZipEntry.cs:line 925     
    at ICSharpCode.SharpZipLib.Zip.ZipInputStream.GetNextEntry() in C:\C#\SharpZLib\Zip\ZipInputStream.cs:line 269     
    at Constellation.Utils.Tools.UnzipFile(String sourcePath, String targetDirectory) in C:\C#\Constellation2\Utils\Tools.cs:line 90     
--- End of inner exception stack trace ---

Here is my unzip method:

     public static void UnzipFile(string sourcePath, string targetDirectory)
     {
        try
        {
            using (ZipInputStream s = new ZipInputStream(File.OpenRead(sourcePath)))
            {
                ZipEntry theEntry;
                while ((theEntry = s.GetNextEntry()) != null)
                {
                    //string directoryName = Path.GetDirectoryName(theEntry.Name);
                    string fileName = Path.GetFileName(theEntry.Name);

                    if (targetDirectory.Length > 0)
                    {
                        Directory.CreateDirectory(targetDirectory);
                    }

                    if (fileName != String.Empty)
                    {
                        using (FileStream streamWriter = File.Create(targetDirectory + fileName))
                        {
                            int size = 2048;
                            byte[] data = new byte[2048];
                            while (true)
                            {
                                size = s.Read(data, 0, data.Length);
                                if (size > 0)
                                {
                                    streamWriter.Write(data, 0, size);
                                }
                                else
                                {
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
        catch (Exception ex)
        {
            throw new Exception("Error unzipping file \"" + sourcePath + "\"", ex);
        }
    }

The file unzips fine using XP's built-in ZIP support, WinZIP, and 7-Zip. The exception is being thrown at s.GetNextEntry().

4

4 Answers

1
votes

It's possible that the other zip tools are ignoring extra data which is corrupt - or it's equally possible that there's a bug in #ZipLib. (I found one a while ago - a certain file that wouldn't compress and then decompress cleanly with certain options.)

In this particular case, I suggest you post on the #ZipLib forum to get the attention of the developers. If your file doesn't contain any sensitive data and you can get them a short but complete program along with it, I suspect that will help enormously.

0
votes

I agree with Jon. Couldn't fit following in the comment:

(Though this doesn't answer your question) Isn't it easier to use something like this:

public static void UnzipFile(string sourcePath, string targetDirectory)
{
    try
    {
        FastZip fastZip = new FastZip();
        fastZip.CreateEmptyDirectories = false;
        fastZip.ExtractZip(sourcePath, targetDirectory,"");
    }
    catch(Exception ex)
    {
        throw new Exception("Error unzipping file \"" + sourcePath + "\"", ex);
    }
}
0
votes

See the official ZIP specification.

Each file in a ZIP archive can have an 'extra' field associated with it. I think #ZipLib is telling you that the 'extra' field length given was longer than the amount of data that was available to read; in other words, the ZIP file has most likely been truncated.

0
votes

According to 4.5.3 of official ZIP specification, fields Size & CompressedSize of extra data "MUST only appear if the corresponding Local or Central directory record field is set to 0xFFFF or 0xFFFFFFFF".

But SharpZipLib writes its at method ZipFile.WriteCentralDirectoryHeader only if "useZip64_ == UseZip64.On". I added entry.IsZip64Forced() condition and bug dissapears)

            if ( entry.CentralHeaderRequiresZip64 ) {
            ed.StartNewEntry();

            if ((entry.Size >= 0xffffffff) || (useZip64_ == UseZip64.On) || entry.IsZip64Forced())
            {
                ed.AddLeLong(entry.Size);
            }

            if ((entry.CompressedSize >= 0xffffffff) || (useZip64_ == UseZip64.On) || entry.IsZip64Forced())
            {
                ed.AddLeLong(entry.CompressedSize);
            }