如何正确地创建ZipArchive? [英] How to create ZipArchive correctly?
问题描述
我正在写的桌面WPF应用程序(.NET框架4.5)和任务之一,是将多个文件保存为zip压缩文档。我做了2种方法。首先要创建zip,第二从中读取数据。
公共静态字符串GetFileContent(字符串zipPath,字符串的entityName)
{
字符串retVal的=的String.Empty;
使用(ZipArchive zip文件= ZipFile.OpenRead(zipPath))
{
的foreach(在zipfile.Entries ZipArchiveEntry项)
{
如果(入门.Name.ToLower()==的entityName)
{使用
(StreamReader的S =新的StreamReader(entry.Open()))
{
retVal的= s.ReadToEnd() ;
中断;
}
}
}
}
返回retVal的;
}
公共静态无效SetArchive(字符串路径,字符串zipName,字典<字符串,字符串>文件)
{
使用(VAR FILESTREAM =新的FileStream(路径.Combine(路径,zipName),FileMode.OpenOrCreate))
{
使用(ZipArchive邮编=新的ZipArchive(FILESTREAM,ZipArchiveMode.Create))
{
的foreach(KeyValuePair<字符串,字符串>文件中的文件)
{
VAR进入= zip.CreateEntry(file.Key,CompressionLevel.Optimal);
使用(流S = entry.Open())
{
字节[]数据= Encoding.UTF8.GetBytes(file.Value);
s.Write(数据,0,data.Length);
}
}
}
}
}
事情是创建和远经理和WinRAR的可以打开它的zip压缩包,但是当我使用第二种方法来读取其内容我不断收到
预计在结束中央目录条目的数量不对应于中央目录条目数。
在System.IO.Compression.ZipArchive.ReadCentralDirectory()在System.IO.Compression.ZipArchive.get_Entries
()
在Microsoft.MCS.SPPal.Storage.StorageObject.GetFileContent(字符串zipPath,字符串的entityName)在Z:\Home Inc\Microsoft.MCS.SPPal\Microsoft.MCS.SPPal\Storage\StorageObject.cs:在Microsoft.MCS.SPPal.MainWindow线32
。 .ctor()中的Z:\Home Inc\Microsoft.MCS.SPPal\Microsoft.MCS.SPPal\MainWindow.xaml.cs:48行
块引用>
作为试验的一部分,我在遥远管理器创建新的存档,并与GetFileContent方法打开它,和它的作品就像一个魅力。所以,我认为错误应该在SetArchive方法。
任何帮助将是真棒,这是凌晨3点,我很坚持。
PS:我知道,代码设计吮吸,它被改写数十次
解决方案
有关更好的压缩,您可以使用7zip的库。通过这种方式:
块引用>
公共无效AddToArchive(字符串fileToBeZipped,串zipDestination)
{
DirectoryInfo的DI =新DirectoryInfo的(zipDestination);
StringBuilder的sb_archiveFile =新的StringBuilder(zipDestination + Path.DirectorySeparatorChar + Di.Name + @7z格式);
串archiveFile = sb_archiveFile.ToString();
SevenZip.SevenZipCompressor压缩机=新SevenZipCompressor();
Console.WriteLine(ZIP目标:+ Di.Name);
如果
{
Console.WriteLine(追加{0}到压缩文件,fileToBeZipped)(File.Exists(fileToBeZipped)!);
compressor.CompressionMode = SevenZip.CompressionMode.Append;
}
,否则
{
Console.WriteLine(创建{0}的目标{1} ....,fileToBeZipped,archiveFile);
Console.WriteLine(创建::);
compressor.CompressionMode = SevenZip.CompressionMode.Create;
}
compressor.CompressionLevel = CompressionLevel.Normal;
compressor.CompressionMethod = CompressionMethod.Lzma;
compressor.CompressionMode = CompressionMode.Append;
compressor.CompressDirectory(zipDestination,archiveFile);
compressor.CompressStream(流光,streamer2);
}
和调用一个方法有:AddToArchive(inFolder,splitIntoDir);
您可以下载7zip的源代码的这里。
您可以安装的NuGet包7zip的的这里的Visual Studio。
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.
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
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
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.
Any help would be awesome, it's 3 a.m. and i'm quite stuck.
P.S: I know code design suck, it was rewritten dozens of times.
解决方案For better compression you can use 7zip library. In this way:
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);
You can download a source code of 7zip here.
You can install a Nuget package for 7zip here for Visual Studio.
这篇关于如何正确地创建ZipArchive?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!