Vorgehensweise: Komprimieren und Extrahieren von Dateien - .NET (2024)

  • Artikel

Der System.IO.Compression-Namespace enthält die folgenden Klassen zum Komprimieren und Dekomprimieren von Dateien und Streams. Sie können diese Typen auch verwenden, um den Inhalt einer komprimierten Datei zu lesen und zu ändern:

  • ZipFile
  • ZipArchive
  • ZipArchiveEntry
  • DeflateStream
  • GZipStream

Anhand der folgenden Beispiele werden einige der Vorgänge erläutert, die Sie mit komprimierten Dateien ausführen können. Für diese Beispiele müssen Ihrem Projekt die folgenden NuGet-Pakete hinzugefügt werden:

Wenn Sie .NET Framework verwenden, fügen Sie Ihrem Projekt Verweise auf diese zwei Bibliotheken hinzu:

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

Beispiel 1: Erstellen und Extrahieren einer ZIP-Datei

Das folgende Beispiel zeigt, wie Sie mithilfe der ZipFile-Klasse eine komprimierte ZIP-Datei erstellen und extrahieren können. In dem Beispiel wird der Inhalt eines Ordners in eine neue ZIP-Datei komprimiert, die anschließend in einen neuen Ordner extrahiert wird.

Wenn Sie das Beispiel ausführen möchten, erstellen Sie in Ihrem Programmordner einen Ordner für den Start, und füllen Sie diesen mit Dateien auf, die gezippt werden sollen.

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.CompressionModule 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 SubEnd Module

Beispiel 2: Extrahieren bestimmter Dateierweiterungen

Im nächsten Beispiel wird der Inhalt einer vorhandenen ZIP-Datei durchlaufen, und Dateien mit der Erweiterung TXT werden extrahiert. Dabei wird die ZipArchive-Klasse verwendet, um auf die ZIP-Datei zuzugreifen, und mithilfe der ZipArchiveEntry-Klasse werden die einzelnen Einträge untersucht. Die Erweiterungsmethode ExtractToFile für das ZipArchiveEntry-Objekt ist in der Klasse System.IO.Compression.ZipFileExtensions verfügbar.

Wenn Sie das Beispiel ausführen möchten, platzieren Sie die ZIP-Datei mit dem Namen result.zip in Ihrem Programmordner. Geben Sie einen Ordnernamen an, in den die Datei extrahiert werden soll, wenn Sie dazu aufgefordert werden.

Wichtig

Beim Entzippen von Dateien müssen Sie auf schädliche Dateipfade achten, die aus dem Verzeichnis weisen können, in das Sie extrahieren möchten. Dies wird als Path Traversal-Angriff bezeichnet. Im folgenden Beispiel wird gezeigt, wie Sie eine Überprüfung auf schädliche Dateipfade durchführen und Dateien sicher entzippen können.

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.IOImports System.IO.CompressionModule 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 SubEnd Module

Beispiel 3: Hinzufügen einer Datei zu einer vorhandenen ZIP-Datei

Im folgenden Beispiel wird die Klasse ZipArchive verwendet, um auf eine vorhandene ZIP-Datei zuzugreifen, der anschließend eine Datei hinzugefügt wird. Die neue Datei wird komprimiert, wenn Sie sie der vorhandenen ZIP-Datei hinzufügen.

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.IOImports System.IO.CompressionModule 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 SubEnd Module

Beispiel 4: Komprimieren und Dekomprimieren von GZ-Dateien

Sie können auch die Klassen GZipStream und DeflateStream verwenden, um Daten zu komprimieren und zu dekomprimieren. Der Komprimierungsalgorithmus ist der gleiche. Es gibt viele beliebte Tools, die Sie verwenden können, um GZipStream-Objekte zu dekomprimieren, die in eine GZ-Datei geschrieben wurden. Das folgende Beispiel zeigt, wie Sie ein Dateiverzeichnis mithilfe der GZipStream-Klasse komprimieren und dekomprimieren:

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.IOImports System.IO.CompressionModule 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 SubEnd Module

Siehe auch

  • ZipArchive
  • ZipFile
  • ZipArchiveEntry
  • DeflateStream
  • GZipStream
  • Datei- und Stream-E/A
Vorgehensweise: Komprimieren und Extrahieren von Dateien - .NET (2024)
Top Articles
Latest Posts
Article information

Author: Saturnina Altenwerth DVM

Last Updated:

Views: 5897

Rating: 4.3 / 5 (64 voted)

Reviews: 95% of readers found this page helpful

Author information

Name: Saturnina Altenwerth DVM

Birthday: 1992-08-21

Address: Apt. 237 662 Haag Mills, East Verenaport, MO 57071-5493

Phone: +331850833384

Job: District Real-Estate Architect

Hobby: Skateboarding, Taxidermy, Air sports, Painting, Knife making, Letterboxing, Inline skating

Introduction: My name is Saturnina Altenwerth DVM, I am a witty, perfect, combative, beautiful, determined, fancy, determined person who loves writing and wants to share my knowledge and understanding with you.