SharpZipLib - ZipException“额外数据结束” - 为什么我会收到此异常?

时间:2008-09-30 19:01:16

标签: c# .net unzip sharpziplib

我正在使用SharpZipLib版本0.85.5来解压缩文件。我的代码已经很好地工作了几个月,直到我找到了一个它不喜欢的ZIP文件。

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 ---

这是我的解压缩方法:

     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);
        }
    }

该文件使用XP的内置ZIP支持,WinZIP和7-Zip解压缩。 s.GetNextEntry()引发了例外情况。

4 个答案:

答案 0 :(得分:1)

其他zip工具可能忽略了损坏的额外数据 - 或者同样可能是#ZipLib中存在错误。 (我刚才发现了一个 - 某个文件不能压缩,然后用某些选项干净地解压缩。)

在这种特殊情况下,我建议您在#ZipLib论坛上发帖,以引起开发人员的注意。如果您的文件不包含任何敏感数据,并且您可以为它们提供一个简短但完整的程序,我怀疑这将有很大帮助。

答案 1 :(得分:0)

我同意乔恩。无法在评论中填写以下内容:

(虽然这不能回答你的问题) 使用这样的东西不是更容易:

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);
    }
}

答案 2 :(得分:0)

请参阅official ZIP specification

ZIP存档中的每个文件都可以有一个与之关联的“额外”字段。我认为#ZipLib告诉你给出的'额外'字段长度比可读取的数据量长;换句话说,ZIP文件很可能被截断了。

答案 3 :(得分:0)

根据official ZIP specification的4.5.3,字段大小& CompressedSize额外数据"只有在相应的Local或Central目录记录字段设置为0xFFFF或0xFFFFFFFF"时才会出现。

但是SharpZipLib仅在" useZip64_ == UseZip64.On"时才在方法ZipFile.WriteCentralDirectoryHeader中写入它。我添加了entry.IsZip64Forced()条件和错误消息

            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);
            }