如何使用C#压缩文件,不使用第三方API?
我很确定这不是重复的,所以只需要一分钟。
我如何编程(C#)压缩文件(在Windows中)而不使用任何第三方库? 我需要一个本地Windows调用或类似的东西; 我真的不喜欢开始一个过程的想法,但如果我绝对必须这样做。 一个PInovke电话会好得多。
否则,让我告诉你我真正想要完成的事情:我需要让用户在一个请求中下载一组文档。 任何想法如何做到这一点?
你使用.NET 3.5吗? 你可以使用ZipPackage
类和相关的类。 它不仅仅是压缩一个文件列表,因为它要为每个添加的文件添加一个MIMEtypes。 它可能做你想要的。
我目前正在使用这些类来解决类似的问题,将多个相关文件归档到一个文件中进行下载。 我们使用文件扩展名将下载文件与我们的桌面应用相关联。 我们遇到的一个小问题是,它不可能使用像7-zip这样的第三方工具来创buildzip文件,因为客户端代码无法打开它 – ZipPackage添加了一个隐藏文件来描述内容types每个组件文件,并且如果该内容types文件丢失,则不能打开一个zip文件。
我如何编程(C#)压缩文件(在Windows中)而不使用任何第三方库?
如果使用4.5框架,现在有ZipArchive和ZipFile类。
using (ZipArchive zip = ZipFile.Open("test.zip", ZipArchiveMode.Create)) { zip.CreateEntryFromFile(@"c:\something.txt", "data/path/something.txt"); }
你需要添加引用:
- System.IO.Compression
- System.IO.Compression.FileSystem
对于.NET核心目标net46,您需要添加依赖关系
- System.IO.Compression
- System.IO.Compression.ZipFile
示例project.json:
"dependencies": { "System.IO.Compression": "4.1.0", "System.IO.Compression.ZipFile": "4.0.1" }, "frameworks": { "net46": {} }
我处于相同的情况,想要.NET而不是第三方库。 作为上面提到的另一个海报,仅仅使用ZipPackage类(在.NET 3.5中引入)是不够的。 为了使ZipPackage正常工作,还有一个附加文件必须包含在存档中。 如果添加这个文件,那么可以直接从Windows资源pipe理器打开生成的ZIP包 – 没问题。
您只需将[Content_Types] .xml文件添加到您希望包含的每个文件扩展名的“Default”节点的归档根目录中。 一旦添加,我可以从Windows资源pipe理器中浏览软件包,或以编程方式解压缩并读取其内容。
有关[Content_Types] .xml文件的更多信息可以在这里find: http : //msdn.microsoft.com/en-us/magazine/cc163372.aspx
以下是[Content_Types] .xml(必须正确命名)文件的示例:
<?xml version="1.0" encoding="utf-8" ?> <Types xmlns= "http://schemas.openxmlformats.org/package/2006/content-types"> <Default Extension="xml" ContentType="text/xml" /> <Default Extension="htm" ContentType="text/html" /> <Default Extension="html" ContentType="text/html" /> <Default Extension="rels" ContentType= "application/vnd.openxmlformats-package.relationships+xml" /> <Default Extension="jpg" ContentType="image/jpeg" /> <Default Extension="png" ContentType="image/png" /> <Default Extension="css" ContentType="text/css" /> </Types>
和C#创build一个ZIP文件:
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)) { source.CopyTo(File.OpenWrite(target)); } } }
注意:
- 此代码使用.NET 4.0中的Stream.CopyTo方法
- 随着.NET 4.5中的ZipArchive类的引入,这将变得更加简单: http : //msdn.microsoft.com/en-us/library/system.io.compression.ziparchive( v = vs.110) .aspx
对于我使用SharpZipLib的.NET 2.0应用程序。 易于使用和开源。
private static string CompressFile(string sourceFileName) { using (ZipArchive archive = ZipFile.Open(Path.ChangeExtension(sourceFileName, ".zip"), ZipArchiveMode.Create)) { archive.CreateEntryFromFile(sourceFileName, Path.GetFileName(sourceFileName)); } return Path.ChangeExtension(sourceFileName, ".zip"); }
根据Simon McKenzie 对这个问题的回答,我build议使用这样一对方法:
public static void ZipFolder(string sourceFolder, string zipFile) { if (!System.IO.Directory.Exists(sourceFolder)) throw new ArgumentException("sourceDirectory"); byte[] zipHeader = new byte[] { 80, 75, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; using (System.IO.FileStream fs = System.IO.File.Create(zipFile)) { fs.Write(zipHeader, 0, zipHeader.Length); } dynamic shellApplication = Activator.CreateInstance(Type.GetTypeFromProgID("Shell.Application")); dynamic source = shellApplication.NameSpace(sourceFolder); dynamic destination = shellApplication.NameSpace(zipFile); destination.CopyHere(source.Items(), 20); } public static void UnzipFile(string zipFile, string targetFolder) { if (!System.IO.Directory.Exists(targetFolder)) System.IO.Directory.CreateDirectory(targetFolder); dynamic shellApplication = Activator.CreateInstance(Type.GetTypeFromProgID("Shell.Application")); dynamic compressedFolderContents = shellApplication.NameSpace(zipFile).Items; dynamic destinationFolder = shellApplication.NameSpace(targetFolder); destinationFolder.CopyHere(compressedFolderContents); } }
看起来像Windows可能只是让你这样做…
不幸的是,我不认为你会开始一个单独的进程,除非你去第三方组件。