如何使用内置的.net压缩类压缩目录?

问题描述 投票:2回答:6

使用System.IO.Compression命名空间类GZIPStream和DeflateStream我成功地可以压缩和解压缩单个文件。但是,如果我将目录名作为压缩目标传递,则会出现安全性异常。我是否必须(递归地)枚举所有文件和子目录以便能够压缩目录?

(可能来自codeplex的dotnetzip会更好地处理这个问题,但这不是我现在所追求的)。

.net compression
6个回答
4
投票

当你使用GZipStream等时,你正在压缩一个流;不是文件。 GZip没有文件头信息,因此没有合理的方法来打包多个文件。为此你需要像.zip这样的东西; #ziplib将完成这项工作,但您仍然(IIRC)需要手动为其提供每个文件。


4
投票

System.IO.Compression类无法管理多文件归档。您需要自己做一些工作来创建跟踪存档中内容的文件格式。本文可能会帮助您入门:

How to compress folders and multiple files with GZipStream and C# (System.IO.Compression.GZipStream)

但是,如果您正在使用一种格式,您可以与只有WinZip或WinRAR的用户交换文件,那么您最好选择像SharpZipLib这样的内容。


3
投票

System.IO.Compression中的类只处理流,是的。你必须自己做文件处理。我想,你可以使用SharpZipLib或类似方法来tar文件,然后压缩生成的tar文件。简单如(未经测试):

using (Stream out = new FileStream("out.tar", FileMode.CreateNew))
{
    TarArchive archive = TarArchive.CreateOutputTarArchive(outStream
                                    , TarBuffer.DefaultBlockFactor);
    foreach (string name in fileNames)
    {
        TarEntry entry = TarEntry.CreateEntryFromFile(name);
        archive.WriteEntry(entry, true);
    }
}

1
投票

人们之前已经提到过这一点,内置的.Net类是一个很好的压缩流而不是目录结构。

他们还提到sharpziplib等是很好的库,我同意。他们提供有用的Zip和Tar实现。

但是......如果你的双手被捆绑并且你不能使用这些库,请记住tar format非常简单。实现:Stream ToTar(string path)是一个相当简单和直接的任务(与实现压缩算法不同)


1
投票

这将使用Powershell和System.IO.Packaging.ZipPackage将内容压缩为。\ out.zip,例如here

$zipArchive = $pwd.path + "\out.zip"
[System.Reflection.Assembly]::Load("WindowsBase,Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")
$ZipPackage=[System.IO.Packaging.ZipPackage]::Open($zipArchive, [System.IO.FileMode]"OpenOrCreate", [System.IO.FileAccess]"ReadWrite")
$in = gci .\in | select -expand fullName
[array]$files = $in -replace "C:","" -replace "\\","/"
ForEach ($file In $files) {
   $partName=New-Object System.Uri($file, [System.UriKind]"Relative")
   $part=$ZipPackage.CreatePart($partName, "application/zip", [System.IO.Packaging.CompressionOption]"Maximum")
   $bytes=[System.IO.File]::ReadAllBytes($file)
   $stream=$part.GetStream()
   $stream.Write($bytes, 0, $bytes.Length)
   $stream.Close()
                                                    }
$ZipPackage.Close()

0
投票

您可以在纯.NET 3.0中压缩目录。

首先,您需要对WindowsBase.dll的引用。

此代码将打开或创建一个zip文件,在其中创建一个目录,并将该文件放在该目录中。如果要压缩文件夹(可能包含子目录),可以遍历目录中的文件并为每个文件调用此方法。然后,您可以深度优先搜索子目录中的文件,为每个文件调用方法并传入路径以在zip文件中创建该层次结构。

public void AddFileToZip(string zipFilename, string fileToAdd, string destDir)
{
    using (Package zip = System.IO.Packaging.Package.Open(zipFilename, FileMode.OpenOrCreate))
    {
        string destFilename = "." + destDir + "\\" + Path.GetFileName(fileToAdd);
        Uri uri = PackUriHelper.CreatePartUri(new Uri(destFilename, UriKind.Relative));
        if (zip.PartExists(uri))
        {
            zip.DeletePart(uri);
        }
        PackagePart part = zip.CreatePart(uri, "", CompressionOption.Normal);

        using (FileStream fileStream = new FileStream(fileToAdd, FileMode.Open, FileAccess.Read))
        {
            using (Stream dest = part.GetStream())
            {
                CopyStream(fileStream, dest);
            }
        }
    }
}

destDir可以是一个空字符串,它将文件直接放在zip中。

资料来源:https://weblogs.asp.net/jongalloway/creating-zip-archives-in-net-without-an-external-library-like-sharpziplib

https://weblogs.asp.net/albertpascual/creating-a-folder-inside-the-zip-file-with-system-io-packaging

© www.soinside.com 2019 - 2024. All rights reserved.