views:

1521

answers:

3

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

+1  A: 

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.

Jon Skeet
A: 

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);
    }
}
Vivek
A: 

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.

Mike Dimmick