2009-06-02 36 views
139

我很确定这不是重复的,所以只需要一分钟。如何使用C#压缩文件,不使用第三方API?

如何在不使用任何第三方库的情况下以编程方式(C#)压缩文件(在Windows中)?我需要一个本地Windows电话或类似的东西;我真的不喜欢开始一个过程的想法,但如果我绝对必须这样做的话。 PInovke电话会好得多。

如果失败了,让我告诉你我真正想实现的目标:我需要让用户在一个请求中下载文档集合的能力。任何想法如何实现这一目标?

+1

下载? – Cheeso 2009-06-02 16:56:38

+1

@Chesso:是的,来自ASPX页面。 – 2009-06-02 17:18:04

+1

几周前我在搜索同样的东西时发现这个例子有用:http://www.syntaxwarriors.com/2012/zip-files-using-c-net-without-any-extra-libraries/ – JensB 2012-09-23 16:59:31

回答

80

您使用的是.NET 3.5吗?您可以使用ZipPackage类和相关的类。它不仅仅是压缩文件列表,因为它需要为每个添加的文件添加一个MIME类型。它可能会做你想做的事。

我目前正在使用这些类来解决一个类似的问题,将多个相关文件归档到一个文件中进行下载。我们使用文件扩展名将下载文件与桌面应用相关联。我们遇到的一个小问题是,由于客户端代码无法打开它,因此无法使用第三方工具(如7-zip)来创建zip文件 - ZipPackage添加了一个隐藏文件,该文件描述了每个组件文件,并且如果该内容类型文件丢失,则无法打开一个zip文件。

0

看起来像Windows可能会只让你做this ...

不幸的是,我不认为你会避开启动一个单独的进程,除非你去一个第三方组件。

4

对于我使用的.NET 2.0应用程序SharpZipLib。易于使用和开源。

11

我处于相同的情况,想要.NET而不是第三方库。作为上面提到的另一个海报,仅仅使用ZipPackage类(在.NET 3.5中引入)是不够的。为了使ZipPackage正常工作,还必须在档案中包含一个附加文件。如果添加此文件,则可以直接从Windows资源管理器打开生成的ZIP包 - 没问题。

您只需将[Content_Types] .xml文件添加到存档的根目录中,并为每个您希望包含的文件扩展名添加一个“Default”节点。一旦添加,我就可以从Windows资源管理器浏览软件包,或以编程方式解压并读取其内容。

上的[CONTENT_TYPES] .xml文件的更多信息可以在这里找到: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#创建一个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)); 
      } 
     } 
    } 

注:

216

我如何编程(C#)ZIP,而无需使用任何 第三方库(在Windows)的文件?

如果使用4.5+框架,现在有ZipArchiveZipFile类。

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核2.0,只是增加一个简单的使用声明就是所需的全部:

  • using System.IO.Compression;
1

基于关闭西蒙麦肯齐的回答to this question,我建议使用一对这样的方法:从网页

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); 
    } 
} 
3
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"); 
    } 
相关问题