Cara: Mengompresi dan mengekstrak file
Namespace System.IO.Compression berisi kelas berikut untuk mengompresi dan mendekompresi file dan aliran. Anda juga dapat menggunakan jenis ini untuk membaca dan memodifikasi konten file terkompresi:
Contoh berikut menunjukkan beberapa operasi yang dapat Anda lakukan dengan file terkompresi. Contoh-contoh ini memerlukan paket NuGet berikut untuk ditambahkan ke proyek Anda:
Jika Anda menggunakan .NET Framework, tambahkan referensi ke dua pustaka ini ke proyek Anda:
System.IO.Compression
System.IO.Compression.FileSystem
Contoh 1: Membuat dan mengekstrak file .zip
Contoh berikut menunjukkan cara membuat dan mengekstrak file .zip terkompresi menggunakan kelas ZipFile. Contoh ini memadatkan konten folder ke dalam file .zip baru, lalu mengekstrak file ke folder baru.
Untuk menjalankan sampel, buat folder mulai di folder program Anda dan isi dengan file ke 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
Contoh 2: Mengekstrak ekstensi file tertentu
Contoh berikut berulang melalui konten file .zip yang ada dan mengekstrak file dengan ekstensi .txt. Ini menggunakan ZipArchive kelas untuk mengakses file .zip , dan ZipArchiveEntry kelas untuk memeriksa entri individual. Metode ekstensi ExtractToFile untuk objek ZipArchiveEntry tersedia di kelas System.IO.Compression.ZipFileExtensions.
Untuk menjalankan sampel, tempatkan file .zip bernama result.zip di folder program Anda. Saat diminta, berikan nama folder tempat file akan diekstrak.
Penting
Saat membuka zip file, Anda harus mencari jalur file berbahaya, yang dapat melarikan diri dari direktori tempat Anda membuka zip. Ini dikenal sebagai serangan traversal jalur. Contoh berikut menunjukkan cara memeriksa jalur file berbahaya dan menyediakan cara aman untuk membuka zip.
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
Contoh 3: Menambahkan file ke file .zip yang sudah ada
Contoh berikut menggunakan kelas ZipArchive untuk mengakses file .zip yang ada, dan menambahkan file ke dalamnya. File baru dikompresi saat Anda menambahkannya ke file .zip yang ada.
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
Contoh 4: Mengompresi dan mendekompresi file .gz
Anda juga dapat menggunakan kelas GZipStream dan DeflateStream untuk mengompresi dan mendekompresi data. Mereka menggunakan algoritma kompresi yang sama. Anda dapat mendekompresi objek GZipStream yang ditulis ke file .gz menggunakan banyak alat umum. Contoh berikut menunjukkan cara mengompresi dan mendekompresi direktori file menggunakan kelas GZipStream:
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