如何处理路径过长/重复的Zip文件解压缩问题

9
当我在Windows中解压文件时,偶尔会遇到以下问题:
  1. 路径过长(但在创建文件的原始操作系统中是可以的)。
  2. 由于不区分大小写而“重复”的路径。
使用DotNetZip时,每当读取具有这些问题的zip文件时,调用ZipFile.Read(path)将崩溃。这意味着我甚至无法尝试过滤它们。
using (ZipFile zip = ZipFile.Read(path))
{
    ...
}

什么是处理这种文件的最佳方法?
更新:
例如,从这里获取zip文件: https://github.com/MonoReports/MonoReports/zipball/master

Duplicates: https://github.com/MonoReports/MonoReports/tree/master/src/MonoReports.Model/DataSourceType.cs https://github.com/MonoReports/MonoReports/tree/master/src/MonoReports.Model/DatasourceType.cs

这里是关于异常的更多细节:

Ionic.Zip.ZipException: 无法将其读取为ZipFile
---> System.ArgumentException: 已经添加了具有相同键的项。
at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
at System.Collections.Generic.Dictionary2.Insert(TKey key, TValue value, Boolean add)
at System.Collections.Generic.Dictionary
2.Add(TKey key, TValue value)
at Ionic.Zip.ZipFile.ReadCentralDirectory(ZipFile zf)
at Ionic.Zip.ZipFile.ReadIntoInstance(ZipFile zf)

解决方案:

根据@Cheeso的建议,我可以从流中读取所有内容,从而避免重复和路径问题:

//using (ZipFile zip = ZipFile.Read(path))
using (ZipInputStream stream = new ZipInputStream(path))
{
    ZipEntry e;
    while( (e = stream.GetNextEntry()) != null )
    //foreach( ZipEntry e in zip)
    {
        if (e.FileName.ToLower().EndsWith(".cs") ||
            e.FileName.ToLower().EndsWith(".xaml"))
        {
            //var ms = new MemoryStream();
            //e.Extract(ms);
            var sr = new StreamReader(stream);
            {
                //ms.Position = 0;
                CodeFiles.Add(new CodeFile() { Content = sr.ReadToEnd(), FileName = e.FileName });
            }
        }
    }
}

文件是 .zip 还是 .gz 格式的? - SimpleVar
.zip(特指从Github zipfile下载的文件) - gameweld
你能展示一下错误吗?是文件内的路径名有问题吗?还是目标文件位置太长了? - yamen
我更新了问题,使其更加一般化:重复文件和过长的路径都是问题,并包含示例。 - gameweld
2个回答

9

对于 PathTooLongException 问题,我发现你不能使用 DotNetZip。相反,我所做的是调用 7-zip 的命令行版本; 它非常有效。

public static void Extract(string zipPath, string extractPath)
{
    try
    {
        ProcessStartInfo processStartInfo = new ProcessStartInfo
        {
            WindowStyle = ProcessWindowStyle.Hidden,
            FileName = Path.GetFullPath(@"7za.exe"),
            Arguments = "x \"" + zipPath + "\" -o\"" + extractPath + "\""
        };
        Process process = Process.Start(processStartInfo);
        process.WaitForExit();
        if (process.ExitCode != 0) 
        {
            Console.WriteLine("Error extracting {0}.", extractPath);
        }
    }
    catch (Exception e)
    {
        Console.WriteLine("Error extracting {0}: {1}", extractPath, e.Message);
        throw;
    }
}

2
这实际上是我找到的最简单的解决方案。在发表此评论时,值得注意的是,7za.exe在7-zip下载中带有“7-zip extra:…”的描述。(http://www.7-zip.org/download.html) - Dave Welling
Arguments 行不正确,它应该是 Arguments = "x \"" + zipPath + "\" -o\"" + extractPath + "\""(请注意 -o开关和extractPath` 之间没有空格)。 - sigil
谢谢@sigil,根据这个你是正确的,我更新了我的回答。 - Maria Ines Parnisari
1
好的答案。为了避免进程停止并提示覆盖现有内容,您可以在参数中添加“-y”。 - RVid

3

使用 ZipInputStream 进行读取。

ZipFile 类使用文件名作为索引来保持集合。重复的文件名会破坏这一模型。

但是您可以使用 ZipInputStream 来读取您的 ZipFile,这种情况下没有集合或索引。


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