DotNetZip在.Extract时出现BadReadException异常

21

我有一个奇怪的文件,使用DotNetZip压缩后会创建一个“无法解压”的存档文件。当我尝试使用7zip解压它时,会出现错误消息:CRC failed in 'AjaxControlToolkit.dll'. File is broken. 使用7zip手动压缩后可以正常解压。

是否有人遇到过DotNetZip不能正确压缩简单二进制文件的情况?或者是我在错误地使用DotNetZip?

https://dl.dropbox.com/u/65419748/AjaxControlToolkit.dll

using System.IO;
using Ionic.Zip;

namespace ConsoleApplication1
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var source = new FileInfo(@"C:\ZipDemo\AjaxControlToolkit.dll");
            var target = new FileInfo(Path.ChangeExtension(source.FullName, "zip"));
            var folder = new DirectoryInfo(Path.ChangeExtension(source.FullName, null));

            if (target.Exists)
                target.Delete();

            if (folder.Exists)
                folder.Delete(true);

            using (var zip = new ZipFile(target.FullName))
            {
                zip.AddFile(source.FullName, string.Empty);
                zip.Save();
            }

            using (var zip = new ZipFile(target.FullName))
                zip.ExtractAll(folder.FullName);
        }
    }
}

抛出:

Unhandled Exception: Ionic.Zip.BadReadException: bad read of entry AjaxControlToolkit.dll from compressed archive.
   at Ionic.Zip.ZipEntry._CheckRead(Int32 nbytes)
   at Ionic.Zip.ZipEntry.ExtractOne(Stream output)
   at Ionic.Zip.ZipEntry.InternalExtract(String baseDir, Stream outstream, String password)
   at Ionic.Zip.ZipFile._InternalExtractAll(String path, Boolean overrideExtractExistingProperty)
   at Ionic.Zip.ZipFile.ExtractAll(String path)
   at ConsoleApplication1.Program.Main(String[] args) in C:\ZipDemo\ConsoleApplication1\ConsoleApplication1\Program.cs:line 27

编辑:

如果我添加一个额外的字节,它就能正常工作,但这不是一个可接受的解决方案。没有 + 1 会失败。

var bytes = new byte[source.Length + 1];
File.ReadAllBytes(source.FullName).CopyTo(bytes, 0);
zip.AddEntry(source.Name, bytes);

更新:

放弃使用DotNetZip,转而使用SharpZipLib进行简单提取,但是知道DotNetZip出了什么问题肯定会更好,因为它拥有更好的API。

更新2:

文件长度似乎导致问题,1179647和1179649字节可以正确压缩和解压缩。

var source = new FileInfo(@"C:\ZipDemo\foo.txt");
using (var writer = source.CreateText())
    writer.Write(new string('a', 1179648));

如果您尝试使用其他工具(例如WinRar)解压缩它,会发生什么? - Tigran
@Tigran 只是遇到各种错误,例如使用内置的Windows提取器时,我遇到了0x80004005未指定的错误。 - Ilya Kozhevnikov
尝试使用 .net 4.5 中的 ZipArchive,在 System.IO.Compression 中查看是否出现相同的问题。这很可能是一个 bug。 - Meirion Hughes
3个回答

17

你的dll文件大小为53*128k(6954496/131072 = 53),而DotNetZip中存在一个bug,你可以在这里阅读到相关信息:https://dotnetzip.codeplex.com/workitem/14087。在你的代码中,只需使用:

zip.ParallelDeflateThreshold = -1;

对于很多文件,我曾经遇到过这个问题,现在它已经完美地解决了 ;)


这也解决了C#4.5文件压缩方法中的同样问题 :) - Palanikumar
1
谢谢!这是一个简单的解决方案,对我来说已经足够了。按照@laktak建议的修复进行编译可能是更好的选择,但除非您真的需要并行压缩的优化,否则可能是不必要的。很遗憾官方代码库似乎自2011年以来一直处于不活跃状态 - 不确定是否有更新更活跃的新代码库。 - Chaser324
似乎该链接不再直接跳转到与此问题所引用的工作项相关的位置。因此,如果您有兴趣查找工作项,可以点击链接,切换到“问题”选项卡,并在页面上搜索“ZipFile.AddFile fails depending of the file size.”。该问题看起来就是工作项14087。 - Ben.12

4

这是一个bug - 你可以在Zlib\ParallelDeflateOutputStream.cs中修复它。

更改

} while (doAll && (_lastWritten != _latestCompressed));

to

} while (doAll && (_lastWritten != _lastFilled)); 

更多信息请参见https://dotnetzip.codeplex.com/workitem/14087


2

我尝试了以下步骤 -

  • 安装最新版本的DotNetZip
  • 运行你的代码。
  • 出现BadReadException异常

然后尝试这个 -

  • 安装较旧的版本(1.9)的DotNetZip。 (Install-Package DotNetZip -Version 1.9)
  • 运行你的代码
  • 代码正常工作。

我猜这可能是一个bug?


看起来是这样,提交了一个错误 http://dotnetzip.codeplex.com/workitem/16092 无法确定是否还有其他类似的问题,似乎 CodePlex 本身出现了故障,无法显示工作项描述。 - Ilya Kozhevnikov
1
好的。我已经更新了你的错误报告,并提供了一个可行的示例,这对于任何进行故障排除的人都应该很有用。 - Srikanth Venugopalan
这并不是解决方案!随着您更改版本,大小也会发生变化,因此您现在看不到问题...但下一次更新,问题可能会再次出现! - Xaruth
@Xaruth,不太确定我理解你的观点。我所做的只是将一个文件添加到归档文件中,然后提取并与原始文件进行比较。它抛出了一个异常。请参考此问题以获取有关这些行的一些分析。 - Srikanth Venugopalan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接