Как сжать каталог с помощью встроенных классов сжатия .net? - PullRequest
2 голосов
/ 23 мая 2009

Используя классы пространств имен System.IO.Compression GZIPStream и DeflateStream, я успешно могу сжимать и распаковывать отдельные файлы. Однако, если я передаю имя каталога в качестве цели для сжатия, я получаю исключение безопасности. Нужно ли (рекурсивно) перечислять все файлы и подкаталоги, чтобы иметь возможность сжимать каталог?

(Возможно, dotnetzip из codeplex справится с этим лучше, но это не то, чем я являюсь после этого).

Ответы [ 6 ]

4 голосов
/ 23 мая 2009

Классы System.IO.Compression не позволяют управлять многофайловыми архивами. Вам нужно проделать некоторую работу самостоятельно, чтобы создать формат файла, который будет отслеживать, что находится в вашем архиве. Эта статья может помочь вам начать:

Как сжать папки и несколько файлов с помощью GZipStream и C # (System.IO.Compression.GZipStream)

Однако если вы предпочитаете формат, в котором вы можете обмениваться файлами с пользователями, у которых есть только WinZip или WinRAR, то вам лучше рассмотреть что-то вроде SharpZipLib .

4 голосов
/ 23 мая 2009

Когда вы используете GZipStream и т. Д., Вы сжимаете поток ; не файл. GZip не содержит информации заголовка файла, поэтому нет разумного способа упаковки нескольких файлов. Для этого вам нужно что-то вроде .zip; #ziplib выполнит эту работу, но вам все же (IIRC) необходимо подать каждый файл вручную.

3 голосов
/ 23 мая 2009

Классы в 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 голос
/ 19 октября 2012

Это сжимает. \ In content в. \ Out.zip с Powershell и System.IO.Packaging.ZipPackage, следуя примеру здесь

$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()
1 голос
/ 23 мая 2009

Люди уже упоминали об этом раньше, встроенные классы .Net хороши для сжатия потоков, а не структур каталогов.

Они также упомянули, что sharpziplib и т. Д. Являются хорошими библиотеками для использования, я согласен. Они предлагают реализации Zip и Tar, которые полезны.

Но ... если ваши руки связаны, и вы не можете использовать эти библиотеки, имейте в виду, что формат tar действительно прост. Реализация: Stream ToTar(string path) - довольно простая и простая задача (в отличие от реализации алгоритмов сжатия)

0 голосов
/ 13 апреля 2019

Вы можете сжать каталог в чистом .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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...