Nasıl yapılır: dosyaları sıkıştırma ve ayıklama
System.IO.CompressionAd alanı, dosyaları ve akışları sıkıştırmak ve sıkıştırmayı açma için aşağıdaki türleri içerir. Bu türleri, sıkıştırılmış bir dosyanın içeriğini okumak ve değiştirmek için de kullanabilirsiniz.
Aşağıdaki örneklerde, sıkıştırılmış dosyalarla gerçekleştirebileceğiniz bazı işlemler gösterilmektedir. bu örnekler, aşağıdaki NuGet paketlerinin projenize eklenmesini gerektirir:
.NET Framework kullanıyorsanız, projenize bu iki kitaplıklara başvurular ekleyin:
System.IO.CompressionSystem.IO.Compression.FileSystem
Örnek 1: .zip dosyası oluşturma ve ayıklama
Aşağıdaki örnek, sınıfını kullanarak sıkıştırılmış bir .zip dosyası oluşturmayı ve ayıklamayı gösterir ZipFile . Örnek, bir klasörün içeriğini yeni bir .zip dosyasına sıkıştırır ve sonra zip ' i yeni bir klasöre ayıklar.
Örneği çalıştırmak için, program klasörünüzde bir Başlangıç klasörü oluşturun ve dosyaları ZIP 'e göre doldurun.
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
Örnek 2: belirli dosya uzantılarını ayıklama
Sonraki örnek, var olan bir .zip dosyanın içeriği boyunca yinelenir ve .txt uzantısına sahip dosyaları ayıklar. ZipArchiveZIP 'e erişmek için sınıfını ve ZipArchiveEntry tek tek girişleri incelemek için sınıfını kullanır. Nesnesinin genişletme yöntemi ExtractToFile ZipArchiveEntry System.IO.Compression.ZipFileExtensions sınıfında kullanılabilir.
Örneği çalıştırmak için program klasörünüze result.zip adlı bir .zip dosyası yerleştirin. İstendiğinde, ' a Ayıklanacak bir klasör adı belirtin.
Önemli
Dosyaları kaldırdığınızda, geri yüklediğiniz dizinden çıkmak için kötü amaçlı dosya yolları araması yapmanız gerekir. Bu, yol çapraz geçişi saldırısı olarak bilinir. Aşağıdaki örnek, kötü amaçlı dosya yollarının nasıl denetleyeceğinizi ve sıkıştırmayı açmak için güvenli bir yol sağlar.
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
Örnek 3: mevcut bir zip dosyasına dosya ekleme
Aşağıdaki örnek, varolan bir ZipArchive .zip dosyasına erişmek için sınıfını kullanır ve bu dosyaya bir dosya ekler. Yeni dosya, var olan zip 'e eklediğinizde sıkıştırılır.
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
Örnek 4:. gz dosyalarını sıkıştır ve aç
Ayrıca, GZipStream DeflateStream verileri sıkıştırmak ve açmak için ve sınıflarını da kullanabilirsiniz. Aynı sıkıştırma algoritmasını kullanır. GZipStreamBirçok ortak araç kullanarak bir . gz dosyasına yazılmış nesneleri açabilirsiniz. Aşağıdaki örnek, sınıfını kullanarak bir dosya dizinini nasıl sıkıştırmak ve açmak gösterilmektedir 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