wpf 如何正确创建 ZipArchive?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16226092/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to create ZipArchive correctly?
提问by Silverlay
i'm writing Desktop WPF application (.Net Framework 4.5) and one of tasks is to save multiple files to zip archive. I made 2 methods. First to create zip, second to read from it.
我正在编写桌面 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);
}
}
}
}
}
Thing is that zip archive created and far manager and WinRAR can open it, but when I use second method to read its content I keep getting
事情是创建了 zip 存档并且远程管理器和 WinRAR 可以打开它,但是当我使用第二种方法读取其内容时,我不断收到
Number of entries expected in End Of Central Directory does not correspond to number of entries in Central Directory. at System.IO.Compression.ZipArchive.ReadCentralDirectory() at System.IO.Compression.ZipArchive.get_Entries() at Microsoft.MCS.SPPal.Storage.StorageObject.GetFileContent(String zipPath, String entityName) in z:\Home Inc\Microsoft.MCS.SPPal\Microsoft.MCS.SPPal\Storage\StorageObject.cs:line 32 at Microsoft.MCS.SPPal.MainWindow..ctor() in z:\Home Inc\Microsoft.MCS.SPPal\Microsoft.MCS.SPPal\MainWindow.xaml.cs:line 48
End Of Central Directory 中预期的条目数与 Central Directory 中的条目数不对应。在 System.IO.Compression.ZipArchive.ReadCentralDirectory() 在 System.IO.Compression.ZipArchive.get_Entries() 在 Microsoft.MCS.SPPal.Storage.StorageObject.GetFileContent(String zipPath, String entityName) 在 z:\Home Inc\ Microsoft.MCS.SPPal\Microsoft.MCS.SPPal\Storage\StorageObject.cs:line 32 at Microsoft.MCS.SPPal.MainWindow..ctor() in z:\Home Inc\Microsoft.MCS.SPPal\Microsoft.MCS。 SPPal\MainWindow.xaml.cs:line 48
As a part of experiment i created new archive in far manager and opened it up with GetFileContent method, and it works like a charm. So i think error should be in SetArchive method.
作为实验的一部分,我在远管理器中创建了新存档,并使用 GetFileContent 方法将其打开,它的作用就像一个魅力。所以我认为错误应该在 SetArchive 方法中。
Any help would be awesome, it's 3 a.m. and i'm quite stuck.
任何帮助都会很棒,现在是凌晨 3 点,我被困住了。
P.S: I know code design suck, it was rewritten dozens of times.
PS:我知道代码设计很烂,它被重写了几十次。
采纳答案by Joseph
For better compression you can use 7zip library. In this way:
为了更好地压缩,您可以使用 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);
}
And call a method with: AddToArchive(inFolder, splitIntoDir);
并调用一个方法: AddToArchive(inFolder, splitIntoDir);
You can download a source code of 7zip here.
您可以在此处下载 7zip 的源代码。
You can install a Nuget package for 7zip herefor Visual Studio.
您可以在此处为 Visual Studio安装适用于 7zip 的 Nuget 包。
回答by Stephen Coy
I was able to get this to work by adding an explicit call to Dispose() on the ZipArchive before it went out of scope in the SetArchive() method.
在超出 SetArchive() 方法的范围之前,我能够通过在 ZipArchive 上添加对 Dispose() 的显式调用来使其工作。
zip.Dispose();
回答by Anon
When trying to open zip files containing files that were greater than 4 GB before compression that had been compressed using Deflate64 (created via Windows shell or 7-zip) I got
当尝试打开包含使用 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
when decompressing with System.IO.Compression.ZipFileon Windows 2012 R2. These files seemed to be legitimate zips because Windows Shell, 7-zip and Info-zip could decompress them. The only large file zip archives that decompressed without error with System.IO.Compression.ZipFilewere those created with Info-zip's Zip64.
System.IO.Compression.ZipFile在 Windows 2012 R2 上解压时。这些文件似乎是合法的 zip 文件,因为 Windows Shell、7-zip 和 Info-zip 可以解压缩它们。唯一没有错误解压的大文件 zip 档案是System.IO.Compression.ZipFile用 Info-zip 的 Zip64 创建的。

