我有一堆ZIP文件,迫切需要一些分层重组和提取.目前我能做的是创建目录结构并将zip文件移动到正确的位置.我缺少的神秘奶酪是从ZIP档案中提取文件的部分.
我已经在ZipArchive
课堂上看过MSDN文章并且理解它们很合理.我也看过VBScript的提取方法.这不是一个复杂的类,因此提取东西应该非常简单.事实上,它"主要"起作用.我已将下面的当前代码包含在内以供参考.
using (ZipPackage package = (ZipPackage)Package.Open(@"..\..\test.zip", FileMode.Open, FileAccess.Read)) { PackagePartCollection packageParts = package.GetParts(); foreach (PackageRelationship relation in packageParts) { //Do Stuff but never gets here since packageParts is empty. } }
这个问题似乎存在于某个地方GetParts
(或者就任何事情而言).看来打开的包是空的.深入挖掘调试器显示私有成员_zipArchive显示它实际上有部分.具有正确名称和一切的零件.为什么GetParts
函数不能检索它们?我试过向ZipArchive开放,但没有帮助.哎呀.
如果您正在操作ZIP文件,您可能需要查看第三方库来帮助您.
例如,最近更新过的DotNetZip.目前的版本现在为v1.8.这是创建zip的示例:
using (ZipFile zip = new ZipFile()) { zip.AddFile("c:\\photos\\personal\\7440-N49th.png"); zip.AddFile("c:\\Desktop\\2005_Annual_Report.pdf"); zip.AddFile("ReadMe.txt"); zip.Save("Archive.zip"); }
这是更新现有zip 的示例; 您不需要提取文件来执行此操作:
using (ZipFile zip = ZipFile.Read("ExistingArchive.zip")) { // 1. remove an entry, given the name zip.RemoveEntry("README.txt"); // 2. Update an existing entry, with content from the filesystem zip.UpdateItem("Portfolio.doc"); // 3. modify the filename of an existing entry // (rename it and move it to a sub directory) ZipEntry e = zip["Table1.jpg"]; e.FileName = "images/Figure1.jpg"; // 4. insert or modify the comment on the zip archive zip.Comment = "This zip archive was updated " + System.DateTime.ToString("G"); // 5. finally, save the modified archive zip.Save(); }
这是一个提取条目的示例:
using (ZipFile zip = ZipFile.Read("ExistingZipFile.zip")) { foreach (ZipEntry e in zip) { e.Extract(TargetDirectory, true); // true => overwrite existing files } }
DotNetZip支持文件名中的多字节字符,Zip加密,AES加密,流,Unicode,自解压缩档.对于文件长度大于0xFFFFFFFF,ZIP64也是如此,对于包含超过65535个条目的归档也是如此.
自由.开源
从codeplex获取它 或从windows.net直接下载 - CodePlex已经停产并存档
来自MSDN,
在这个示例中,使用了Package类(而不是ZipPackage.)在使用了两者之后,我只看到当zip文件中存在损坏时会出现片状.抛出Windows提取器或Winzip不一定是腐败,而是包装组件处理有问题的东西.
希望这有帮助,也许它可以为您提供调试问题的替代方案.
using System; using System.IO; using System.IO.Packaging; using System.Text; class ExtractPackagedImages { static void Main(string[] paths) { foreach (string path in paths) { using (Package package = Package.Open( path, FileMode.Open, FileAccess.Read)) { DirectoryInfo dir = Directory.CreateDirectory(path + " Images"); foreach (PackagePart part in package.GetParts()) { if (part.ContentType.ToLowerInvariant().StartsWith("image/")) { string target = Path.Combine( dir.FullName, CreateFilenameFromUri(part.Uri)); using (Stream source = part.GetStream( FileMode.Open, FileAccess.Read)) using (Stream destination = File.OpenWrite(target)) { byte[] buffer = new byte[0x1000]; int read; while ((read = source.Read(buffer, 0, buffer.Length)) > 0) { destination.Write(buffer, 0, read); } } Console.WriteLine("Extracted {0}", target); } } } } Console.WriteLine("Done"); } private static string CreateFilenameFromUri(Uri uri) { char [] invalidChars = Path.GetInvalidFileNameChars(); StringBuilder sb = new StringBuilder(uri.OriginalString.Length); foreach (char c in uri.OriginalString) { sb.Append(Array.IndexOf(invalidChars, c) < 0 ? c : '_'); } return sb.ToString(); } }
来自" ZipPackage Class "(MSDN):
虽然Packages通过ZipPackage类存储为Zip文件*,但所有Zip文件都不是ZipPackages.ZipPackage具有特殊要求,例如符合URI的文件(部分)名称和"[Content_Types] .xml"文件,该文件定义包中包含的所有文件的MIME类型.ZipPackage类不能用于打开不符合Open Packaging Conventions标准的任意Zip文件.
有关详细信息,请参阅ECMA国际"开放式包装约定"标准的第9.2节"映射到ZIP存档",http://www.ecma-international.org/publications/files/ECMA-ST/Office%20Open%20XML% 20Part%202%20(DOCX).zip(342Kb)或http://www.ecma-international.org/publications/files/ECMA-ST/Office%20Open%20XML%20Part%202%20(PDF).zip(1.3MB)
*您只需将".zip"添加到任何基于ZipPackage的文件(.docx,.xlsx,.pptx等)的扩展名,即可在您喜欢的Zip实用程序中打开它.
我有完全相同的问题!为了让GetParts()方法返回一些东西,我不得不将[Content_Types] .xml文件添加到存档的根目录,并为每个包含的文件扩展名添加"默认"节点.一旦我添加了这个(只使用Windows资源管理器),我的代码就能够读取和提取存档的内容.
有关[Content_Types] .xml文件的更多信息,请访问:
http://msdn.microsoft.com/en-us/magazine/cc163372.aspx - 本文的图13下面有一个示例文件.
var zipFilePath = "c:\\myfile.zip"; var tempFolderPath = "c:\\unzipped"; using (Package package = ZipPackage.Open(zipFilePath, FileMode.Open, FileAccess.Read)) { foreach (PackagePart part in package.GetParts()) { var target = Path.GetFullPath(Path.Combine(tempFolderPath, part.Uri.OriginalString.TrimStart('/'))); var targetDir = target.Remove(target.LastIndexOf('\\')); if (!Directory.Exists(targetDir)) Directory.CreateDirectory(targetDir); using (Stream source = part.GetStream(FileMode.Open, FileAccess.Read)) { FileStream targetFile = File.OpenWrite(target); source.CopyTo(targetFile); targetFile.Close(); } } }
注意:此代码使用.NET 4.0中的Stream.CopyTo方法
我同意Cheeso.处理通用zip文件时,System.IO.Packaging很尴尬,因为它是为Office Open XML文档设计的.我建议使用DotNetZip或SharpZipLib