Procedura: Comprimere ed estrarre fileHow to: Compress and extract files

Lo spazio dei nomi System.IO.Compression contiene i tipi seguenti per la compressione e la decompressione di file e flussi.The System.IO.Compression namespace contains the following types for compressing and decompressing files and streams. È possibile usare questi tipi anche per leggere e modificare il contenuto di un file compresso.You can also use these types to read and modify the contents of a compressed file.

Gli esempi seguenti mostrano alcune delle operazioni che è possibile eseguire con i file compressi.The following examples show some of the operations you can perform with compressed files. Per questi esempi è necessario aggiungere al progetto i pacchetti NuGet seguenti:These examples require the following NuGet packages to be added to your project:

Se si usa .NET Framework, aggiungere i riferimenti alle due librerie seguenti al progetto:If you're using .NET Framework, add references to these two libraries to your project:

  • System.IO.Compression
  • System.IO.Compression.FileSystem

Esempio 1: creare ed estrarre un file zipExample 1: Create and extract a .zip file

Nell'esempio seguente viene illustrato come creare ed estrarre un file ZIP compresso usando la classe ZipFile.The following example shows how to create and extract a compressed .zip file by using the ZipFile class. L'esempio comprime il contenuto di una cartella in un nuovo file ZIP e quindi estrae il contenuto in una nuova cartella.The example compresses the contents of a folder into a new .zip file, and then extracts the zip to a new folder.

Per eseguire l'esempio, creare una cartella start nella cartella del programma e copiarvi i file da comprimere.To run the sample, create a start folder in your program folder and populate it with files to zip.

using System;
using System.IO.Compression;

class Program
{
    static void Main(string[] args)
    {
        string startPath = @".\start";
        string zipPath = @".\result.zip";
        string extractPath = @".\extract";

        ZipFile.CreateFromDirectory(startPath, zipPath);

        ZipFile.ExtractToDirectory(zipPath, extractPath);
    }
}
Imports System.IO.Compression

Module Module1

    Sub Main()
        Dim startPath As String = ".\start"
        Dim zipPath As String = ".\result.zip"
        Dim extractPath As String = ".\extract"

        ZipFile.CreateFromDirectory(startPath, zipPath)

        ZipFile.ExtractToDirectory(zipPath, extractPath)
    End Sub

End Module

Esempio 2: estrarre estensioni di file specificheExample 2: Extract specific file extensions

Il prossimo esempio mostra come eseguire l'iterazione del contenuto di un file ZIP esistente ed estrarre i file con estensione txt.The next example iterates through the contents of an existing .zip file and extracts files that have a .txt extension. Usa la classe ZipArchive per accedere al file ZIP e la classe ZipArchiveEntry per controllare le singole voci.It uses the ZipArchive class to access the zip, and the ZipArchiveEntry class to inspect the individual entries. Il metodo di estensione ExtractToFile per l'oggetto ZipArchiveEntry è disponibile nella classe System.IO.Compression.ZipFileExtensions.The extension method ExtractToFile for the ZipArchiveEntry object is available in the System.IO.Compression.ZipFileExtensions class.

Per eseguire l'esempio, inserire un file ZIP denominato result.zip nella cartella del programma.To run the sample, place a .zip file called result.zip in your program folder. Quando richiesto, specificare un nome di cartella in cui estrarre i file.When prompted, provide a folder name to extract to.

Importante

Quando si decomprimono i file, è necessario cercare percorsi dannosi che possono sfuggire alla directory in cui si esegue la decompressione.When unzipping files, you must look for malicious file paths, which can escape out of the directory you unzip into. Si tratta di un attacco noto come attacco path traversal.This is known as a path traversal attack. L'esempio seguente illustra come verificare la presenza di percorsi file dannosi e offre un metodo sicuro per la decompressione.The following example demonstrates how to check for malicious file paths and provides a safe way to unzip.

using System;
using System.IO;
using System.IO.Compression;

class Program
{
    static void Main(string[] args)
    {
        string zipPath = @".\result.zip";

        Console.WriteLine("Provide path where to extract the zip file:");
        string extractPath = Console.ReadLine();

        // Normalizes the path.
        extractPath = Path.GetFullPath(extractPath);

        // Ensures that the last character on the extraction path
        // is the directory separator char.
        // Without this, a malicious zip file could try to traverse outside of the expected
        // extraction path.
        if (!extractPath.EndsWith(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal))
            extractPath += Path.DirectorySeparatorChar;

        using (ZipArchive archive = ZipFile.OpenRead(zipPath))
        {
            foreach (ZipArchiveEntry entry in archive.Entries)
            {
                if (entry.FullName.EndsWith(".txt", StringComparison.OrdinalIgnoreCase))
                {
                    // Gets the full path to ensure that relative segments are removed.
                    string destinationPath = Path.GetFullPath(Path.Combine(extractPath, entry.FullName));

                    // Ordinal match is safest, case-sensitive volumes can be mounted within volumes that
                    // are case-insensitive.
                    if (destinationPath.StartsWith(extractPath, StringComparison.Ordinal))
                        entry.ExtractToFile(destinationPath);
                }
            }
        }
    }
}
Imports System.IO
Imports System.IO.Compression

Module Module1

    Sub Main()
        Dim zipPath As String = ".\result.zip"

        Console.WriteLine("Provide path where to extract the zip file:")
        Dim extractPath As String = Console.ReadLine()

        ' Normalizes the path.
        extractPath = Path.GetFullPath(extractPath)

        ' Ensures that the last character on the extraction path
        ' is the directory separator char. 
        ' Without this, a malicious zip file could try to traverse outside of the expected
        ' extraction path.
        If Not extractPath.EndsWith(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal) Then
            extractPath += Path.DirectorySeparatorChar
        End If

        Using archive As ZipArchive = ZipFile.OpenRead(zipPath)
            For Each entry As ZipArchiveEntry In archive.Entries
                If entry.FullName.EndsWith(".txt", StringComparison.OrdinalIgnoreCase) Then

                    ' Gets the full path to ensure that relative segments are removed.
                    Dim destinationPath As String = Path.GetFullPath(Path.Combine(extractPath, entry.FullName))

                    ' Ordinal match is safest, case-sensitive volumes can be mounted within volumes that
                    ' are case-insensitive.
                    If destinationPath.StartsWith(extractPath, StringComparison.Ordinal) Then
                        entry.ExtractToFile(destinationPath)
                    End If

                End If
            Next
        End Using
    End Sub

End Module

Esempio 3: aggiungere un file a un file Zip esistenteExample 3: Add a file to an existing zip

L'esempio seguente usa la classe ZipArchive per accedere a un file ZIP esistente e aggiunge un nuovo file al file compresso.The following example uses the ZipArchive class to access an existing .zip file, and adds a file to it. Il nuovo file viene compresso quando lo si aggiunge al file ZIP esistente.The new file gets compressed when you add it to the existing zip.

using System;
using System.IO;
using System.IO.Compression;

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            using (FileStream zipToOpen = new FileStream(@"c:\users\exampleuser\release.zip", FileMode.Open))
            {
                using (ZipArchive archive = new ZipArchive(zipToOpen, ZipArchiveMode.Update))
                {
                    ZipArchiveEntry readmeEntry = archive.CreateEntry("Readme.txt");
                    using (StreamWriter writer = new StreamWriter(readmeEntry.Open()))
                    {
                            writer.WriteLine("Information about this package.");
                            writer.WriteLine("========================");
                    }
                }
            }
        }
    }
}
Imports System.IO
Imports System.IO.Compression

Module Module1

    Sub Main()
        Using zipToOpen As FileStream = New FileStream("c:\users\exampleuser\release.zip", FileMode.Open)
            Using archive As ZipArchive = New ZipArchive(zipToOpen, ZipArchiveMode.Update)
                Dim readmeEntry As ZipArchiveEntry = archive.CreateEntry("Readme.txt")
                Using writer As StreamWriter = New StreamWriter(readmeEntry.Open())
                    writer.WriteLine("Information about this package.")
                    writer.WriteLine("========================")
                End Using
            End Using
        End Using
    End Sub

End Module

Esempio 4: comprimere e decomprimere i file. gzExample 4: Compress and decompress .gz files

È possibile usare anche le classi GZipStream e DeflateStream per comprimere e decomprimere dati.You can also use the GZipStream and DeflateStream classes to compress and decompress data. Queste due classi usano lo stesso algoritmo di compressione.They use the same compression algorithm. È possibile decomprimere gli oggetti GZipStream scritti in un file con estensione gz con molti strumenti comuni.You can decompress GZipStream objects that are written to a .gz file by using many common tools. L'esempio seguente illustra come comprimere e decomprimere una directory di file usando la classe GZipStream:The following example shows how to compress and decompress a directory of files by using the GZipStream class:

using System;
using System.IO;
using System.IO.Compression;

public class Program
{
    private static string directoryPath = @".\temp";
    public static void Main()
    {
        DirectoryInfo directorySelected = new DirectoryInfo(directoryPath);
        Compress(directorySelected);

        foreach (FileInfo fileToDecompress in directorySelected.GetFiles("*.gz"))
        {
            Decompress(fileToDecompress);
        }
    }

    public static void Compress(DirectoryInfo directorySelected)
    {
        foreach (FileInfo fileToCompress in directorySelected.GetFiles())
        {
            using (FileStream originalFileStream = fileToCompress.OpenRead())
            {
                if ((File.GetAttributes(fileToCompress.FullName) &
                   FileAttributes.Hidden) != FileAttributes.Hidden & fileToCompress.Extension != ".gz")
                {
                    using (FileStream compressedFileStream = File.Create(fileToCompress.FullName + ".gz"))
                    {
                        using (GZipStream compressionStream = new GZipStream(compressedFileStream,
                           CompressionMode.Compress))
                        {
                            originalFileStream.CopyTo(compressionStream);
                        }
                    }
                    FileInfo info = new FileInfo(directoryPath + Path.DirectorySeparatorChar + fileToCompress.Name + ".gz");
                    Console.WriteLine($"Compressed {fileToCompress.Name} from {fileToCompress.Length.ToString()} to {info.Length.ToString()} bytes.");
                }
            }
        }
    }

    public static void Decompress(FileInfo fileToDecompress)
    {
        using (FileStream originalFileStream = fileToDecompress.OpenRead())
        {
            string currentFileName = fileToDecompress.FullName;
            string newFileName = currentFileName.Remove(currentFileName.Length - fileToDecompress.Extension.Length);

            using (FileStream decompressedFileStream = File.Create(newFileName))
            {
                using (GZipStream decompressionStream = new GZipStream(originalFileStream, CompressionMode.Decompress))
                {
                    decompressionStream.CopyTo(decompressedFileStream);
                    Console.WriteLine($"Decompressed: {fileToDecompress.Name}");
                }
            }
        }
    }
}
Imports System.IO
Imports System.IO.Compression

Module Module1

    Private directoryPath As String = ".\temp"
    Public Sub Main()
        Dim directorySelected As New DirectoryInfo(directoryPath)
        Compress(directorySelected)

        For Each fileToDecompress As FileInfo In directorySelected.GetFiles("*.gz")
            Decompress(fileToDecompress)
        Next
    End Sub

    Public Sub Compress(directorySelected As DirectoryInfo)
        For Each fileToCompress As FileInfo In directorySelected.GetFiles()
            Using originalFileStream As FileStream = fileToCompress.OpenRead()
                If (File.GetAttributes(fileToCompress.FullName) And FileAttributes.Hidden) <> FileAttributes.Hidden And fileToCompress.Extension <> ".gz" Then
                    Using compressedFileStream As FileStream = File.Create(fileToCompress.FullName & ".gz")
                        Using compressionStream As New GZipStream(compressedFileStream, CompressionMode.Compress)

                            originalFileStream.CopyTo(compressionStream)
                        End Using
                    End Using
                    Dim info As New FileInfo(directoryPath & Path.DirectorySeparatorChar & fileToCompress.Name & ".gz")
                    Console.WriteLine($"Compressed {fileToCompress.Name} from {fileToCompress.Length.ToString()} to {info.Length.ToString()} bytes.")

                End If
            End Using
        Next
    End Sub


    Private Sub Decompress(ByVal fileToDecompress As FileInfo)
        Using originalFileStream As FileStream = fileToDecompress.OpenRead()
            Dim currentFileName As String = fileToDecompress.FullName
            Dim newFileName = currentFileName.Remove(currentFileName.Length - fileToDecompress.Extension.Length)

            Using decompressedFileStream As FileStream = File.Create(newFileName)
                Using decompressionStream As GZipStream = New GZipStream(originalFileStream, CompressionMode.Decompress)
                    decompressionStream.CopyTo(decompressedFileStream)
                    Console.WriteLine($"Decompressed: {fileToDecompress.Name}")
                End Using
            End Using
        End Using
    End Sub
End Module

Vedere ancheSee also