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

时间:2009-05-22 21:15:16

标签: .net compression

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

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

6 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分:4)

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

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

但是,如果您使用的格式可以与只有WinZip或WinRAR的用户交换文件,那么您最好不要查看SharpZipLib之类的内容。

答案 2 :(得分: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);
    }
}

答案 3 :(得分:1)

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

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

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

答案 4 :(得分: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()

答案 5 :(得分: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