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

发布于 2024-07-05 17:33:54 字数 2667 浏览 10 评论 0原文

我正在使用 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() 处引发。

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

指尖微凉心微凉 2024-07-12 17:33:54

根据官方ZIP规范的4.5.3,字段Size & 额外数据的压缩大小“仅当相应的本地或中央目录记录字段设置为 0xFFFF 或 0xFFFFFFFF 时才必须出现”。

但是,仅当“useZip64_ == UseZip64.On”时,SharpZipLib 才会将其写入方法 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);
            }

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);
            }
红墙和绿瓦 2024-07-12 17:33:54

请参阅官方 ZIP 规范

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

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.

旧人九事 2024-07-12 17:33:54

我同意乔恩的观点。 无法在评论中添加以下内容:(

尽管这不能回答您的问题)
使用这样的东西不是更容易吗:

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

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);
    }
}
捂风挽笑 2024-07-12 17:33:54

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

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文