如何正确创建ZipArchive?

时间:2013-04-25 22:55:34

标签: c# .net wpf .net-4.5 zipfile

我正在编写桌面WPF应用程序(.Net Framework 4.5),其中一项任务是将多个文件保存到zip存档。我做了2个方法。首先创建zip,然后再从中读取。

    public static String GetFileContent(String zipPath, String entityName)
    {
        String retVal = String.Empty;

        using (ZipArchive zipfile = ZipFile.OpenRead(zipPath))
        {                    
            foreach (ZipArchiveEntry entry in zipfile.Entries)
            {
                if (entry.Name.ToLower() == entityName)
                {
                    using (StreamReader s = new StreamReader(entry.Open()))
                    {
                        retVal = s.ReadToEnd();
                        break;
                    }
                }
            }
        }

        return retVal;
    }

    public static void SetArchive(String path, String zipName, Dictionary<String, String> files)
    {
        using (var fileStream = new FileStream(Path.Combine(path, zipName), FileMode.OpenOrCreate))
        {
            using (ZipArchive zip = new ZipArchive(fileStream, ZipArchiveMode.Create))
            {                    
                foreach (KeyValuePair<String, String> file in files)
                {
                    var entry = zip.CreateEntry(file.Key, CompressionLevel.Optimal);
                    using (Stream s = entry.Open())
                    {           
                        byte[] data = Encoding.UTF8.GetBytes(file.Value);
                        s.Write(data, 0, data.Length);
                    }
                }                    
            }            
        }
    }

事情是创建了zip存档,远程管理器和WinRAR可以打开它,但当我使用第二种方法来阅读其内容时,我一直在

  

End Of Central Directory中预期的条目数与中央目录中的条目数不对应。      在System.IO.Compression.ZipArchive.ReadCentralDirectory()      在System.IO.Compression.ZipArchive.get_Entries()      位于z:\ Home Inc \ Microsoft.MCS.SPPal \ Microsoft.MCS.SPPal \ Storage \ StorageObject.cs中的Microsoft.MCS.SPPal.Storage.StorageObject.GetFileContent(String zipPath,String entityName):第32行      位于z:\ Home Inc \ Microsoft.MCS.SPPal \ Microsoft.MCS.SPPal \ MainWindow.xaml.cs中的Microsoft.MCS.SPPal.MainWindow..ctor():第48行

作为实验的一部分,我在远程管理器中创建了新的存档,并使用GetFileContent方法打开它,它就像一个魅力。所以我认为错误应该在SetArchive方法中。

任何帮助都会很棒,现在是凌晨3点,而且我很困难。

P.S:我知道代码设计太糟糕了,它被重写了几十次。

3 个答案:

答案 0 :(得分:3)

我可以通过在ZipArchive上添加对Dispose()的显式调用,然后在SetArchive()方法中超出范围之前使其工作。

zip.Dispose();

答案 1 :(得分:0)

当尝试打开包含使用Deflate64(通过Windows shell或7-zip创建)压缩的压缩之前大于4 GB的文件的zip文件时,我得到了

Number of entries expected in End Of Central Directory does not correspond to number of entries in Central Directory

在Windows 2012 R2上使用System.IO.Compression.ZipFile解压缩时。这些文件似乎是合法的拉链,因为Windows Shell,7-zip和Info-zip可以解压缩它们。唯一使用System.IO.Compression.ZipFile解压缩而没有错误的大型文件zip存档是使用Info-zip的Zip64创建的。

答案 2 :(得分:-4)

  

为了更好的压缩,您可以使用7zip库。这样:

public void AddToArchive(string fileToBeZipped, string zipDestination)
{
    DirectoryInfo Di = new DirectoryInfo(zipDestination);
    StringBuilder sb_archiveFile = new StringBuilder(zipDestination + Path.DirectorySeparatorChar + Di.Name + @".7z");
    string archiveFile = sb_archiveFile.ToString();


    SevenZip.SevenZipCompressor compressor = new SevenZipCompressor();

    Console.WriteLine("zip destination : " + Di.Name);
    if (!File.Exists(fileToBeZipped))
    {
        Console.WriteLine("Appending {0} to Archive ", fileToBeZipped);
        compressor.CompressionMode = SevenZip.CompressionMode.Append;
    }
    else
    {
        Console.WriteLine("Creating {0} at Destination {1}....", fileToBeZipped, archiveFile);
        Console.WriteLine("CREATING:: ");
        compressor.CompressionMode = SevenZip.CompressionMode.Create;
    }
    compressor.CompressionLevel = CompressionLevel.Normal;
    compressor.CompressionMethod = CompressionMethod.Lzma;
    compressor.CompressionMode = CompressionMode.Append;

    compressor.CompressDirectory(zipDestination, archiveFile);



    compressor.CompressStream(streamer, streamer2);
}

用以下方法调用方法:AddToArchive(inFolder,splitIntoDir);

您可以下载7zip here的源代码。

您可以为Visual Studio安装7zip here的Nuget包。