How to compress a directory with the built in .net compression classes?

前端 未结 6 818
囚心锁ツ
囚心锁ツ 2021-01-15 19:15

Using the System.IO.Compression namespaces classes GZIPStream and DeflateStream I successfully can compress and decompress individual files. However, if I pass a directoryna

相关标签:
6条回答
  • 2021-01-15 19:30

    When you use GZipStream etc, you are compressing a stream; not a file. GZip has no file header information, so there is no sensible way of packing multiple files. For that you need something like .zip; #ziplib will do the job, but you still (IIRC) need to feed it each file manually.

    0 讨论(0)
  • 2021-01-15 19:31

    This compresses .\in contents to .\out.zip with Powershell and System.IO.Packaging.ZipPackage following the example 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 讨论(0)
  • 2021-01-15 19:38

    The System.IO.Compression classes provide no way to manage multifile archives. You need to do some work on your own to create a file format that track what is in your archive. This article might help you get started:

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

    However if you're after a format that you can exchange files with users who only have WinZip or WinRAR then you're better off looking into something like SharpZipLib.

    0 讨论(0)
  • 2021-01-15 19:40

    People have mentioned this before, the built in .Net classes are good a compressing streams not directory structures.

    They also mentioned that sharpziplib etc.. are good libraries to use, I agree. They offer Zip and Tar implementaions which are useful.

    But... if your hands are tied and you can not use these libs, keep in mind that the tar format is really simple. Implementing: Stream ToTar(string path) is a fairly simple and straight forward task (unlike implementing compression algorithms)

    0 讨论(0)
  • 2021-01-15 19:42

    The classes in System.IO.Compression will only handle streams, yes. You'll have to do file handling yourself. You could, I suppose, use SharpZipLib or similar to tar the files, then compress the resulting tar file. Simple as (untested):

    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);
        }
    }
    
    0 讨论(0)
  • 2021-01-15 19:46

    You can zip the directory in pure .NET 3.0.

    First, you will need a reference to WindowsBase.dll.

    This code will open or create a zip file, create a directory inside, and place the file in that directory. If you want to zip a folder, possibly containing sub-directories, you could loop through the files in the directory and call this method for each file. Then, you could depth-first search the sub-directories for files, call the method for each of those and pass in the path to create that hierarchy within the zip file.

    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 could be an empty string, which would place the file directly in the zip.

    Sources: 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

    0 讨论(0)
提交回复
热议问题