diff --git a/src/SharpCompress/Archives/IArchiveExtensions.cs b/src/SharpCompress/Archives/IArchiveExtensions.cs
index 00aae468..0d39c6e2 100644
--- a/src/SharpCompress/Archives/IArchiveExtensions.cs
+++ b/src/SharpCompress/Archives/IArchiveExtensions.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
-using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using SharpCompress.Common;
@@ -11,135 +10,159 @@ namespace SharpCompress.Archives;
public static class IArchiveExtensions
{
- ///
- /// Extract to specific directory, retaining filename
- ///
- public static void WriteToDirectory(
- this IArchive archive,
- string destinationDirectory,
- ExtractionOptions? options = null
- )
+ /// The archive to extract.
+ extension(IArchive archive)
{
- // For solid archives (Rar, 7Zip), use the optimized reader-based approach
- if (archive.IsSolid || archive.Type == ArchiveType.SevenZip)
+ ///
+ /// Extract to specific directory with progress reporting
+ ///
+ /// The folder to extract into.
+ /// Extraction options.
+ /// Optional progress reporter for tracking extraction progress.
+ public void WriteToDirectory(
+ string destinationDirectory,
+ ExtractionOptions? options = null,
+ IProgress? progress = null
+ )
{
- using var reader = archive.ExtractAllEntries();
- reader.WriteAllToDirectory(destinationDirectory, options);
+ // For solid archives (Rar, 7Zip), use the optimized reader-based approach
+ if (archive.IsSolid || archive.Type == ArchiveType.SevenZip)
+ {
+ using var reader = archive.ExtractAllEntries();
+ reader.WriteAllToDirectory(destinationDirectory, options);
+ }
+ else
+ {
+ // For non-solid archives, extract entries directly
+ archive.WriteToDirectoryInternal(destinationDirectory, options, progress);
+ }
}
- else
+
+ private void WriteToDirectoryInternal(
+ string destinationDirectory,
+ ExtractionOptions? options,
+ IProgress? progress
+ )
{
- // For non-solid archives, extract entries directly
+ // Prepare for progress reporting
+ var totalBytes = archive.TotalUncompressSize;
+ var bytesRead = 0L;
+
+ // Tracking for created directories.
+ var seenDirectories = new HashSet();
+
+ // Extract
foreach (var entry in archive.Entries)
{
- if (!entry.IsDirectory)
+ if (entry.IsDirectory)
{
- entry.WriteToDirectory(destinationDirectory, options);
+ var dirPath = Path.Combine(
+ destinationDirectory,
+ entry.Key.NotNull("Entry Key is null")
+ );
+ if (
+ Path.GetDirectoryName(dirPath + "/") is { } parentDirectory
+ && seenDirectories.Add(dirPath)
+ )
+ {
+ Directory.CreateDirectory(parentDirectory);
+ }
+ continue;
}
+
+ // Use the entry's WriteToDirectory method which respects ExtractionOptions
+ entry.WriteToDirectory(destinationDirectory, options);
+
+ // Update progress
+ bytesRead += entry.Size;
+ progress?.Report(
+ new ProgressReport(entry.Key ?? string.Empty, bytesRead, totalBytes)
+ );
}
}
- }
- ///
- /// Extract to specific directory with progress reporting
- ///
- /// The archive to extract.
- /// The folder to extract into.
- /// Extraction options.
- /// Optional progress reporter for tracking extraction progress.
- public static void WriteToDirectory(
- this IArchive archive,
- string destinationDirectory,
- ExtractionOptions? options,
- IProgress? progress
- )
- {
- // Prepare for progress reporting
- var totalBytes = archive.TotalUncompressSize;
- var bytesRead = 0L;
-
- // Tracking for created directories.
- var seenDirectories = new HashSet();
-
- // Extract
- foreach (var entry in archive.Entries)
+ ///
+ /// Extract to specific directory asynchronously with progress reporting and cancellation support
+ ///
+ /// The folder to extract into.
+ /// Extraction options.
+ /// Optional progress reporter for tracking extraction progress.
+ /// Optional cancellation token.
+ public async Task WriteToDirectoryAsync(
+ string destinationDirectory,
+ ExtractionOptions? options = null,
+ IProgress? progress = null,
+ CancellationToken cancellationToken = default
+ )
{
- if (entry.IsDirectory)
+ // For solid archives (Rar, 7Zip), use the optimized reader-based approach
+ if (archive.IsSolid || archive.Type == ArchiveType.SevenZip)
{
- var dirPath = Path.Combine(
+ using var reader = archive.ExtractAllEntries();
+ await reader.WriteAllToDirectoryAsync(
destinationDirectory,
- entry.Key.NotNull("Entry Key is null")
+ options,
+ cancellationToken
+ );
+ }
+ else
+ {
+ // For non-solid archives, extract entries directly
+ await archive.WriteToDirectoryAsyncInternal(
+ destinationDirectory,
+ options,
+ progress,
+ cancellationToken
);
- if (
- Path.GetDirectoryName(dirPath + "/") is { } parentDirectory
- && seenDirectories.Add(dirPath)
- )
- {
- Directory.CreateDirectory(parentDirectory);
- }
- continue;
}
-
- // Use the entry's WriteToDirectory method which respects ExtractionOptions
- entry.WriteToDirectory(destinationDirectory, options);
-
- // Update progress
- bytesRead += entry.Size;
- progress?.Report(new ProgressReport(entry.Key ?? string.Empty, bytesRead, totalBytes));
}
- }
- ///
- /// Extract to specific directory asynchronously with progress reporting and cancellation support
- ///
- /// The archive to extract.
- /// The folder to extract into.
- /// Extraction options.
- /// Optional progress reporter for tracking extraction progress.
- /// Optional cancellation token.
- public static async Task WriteToDirectoryAsync(
- this IArchive archive,
- string destinationDirectory,
- ExtractionOptions? options = null,
- IProgress? progress = null,
- CancellationToken cancellationToken = default
- )
- {
- // Prepare for progress reporting
- var totalBytes = archive.TotalUncompressSize;
- var bytesRead = 0L;
-
- // Tracking for created directories.
- var seenDirectories = new HashSet();
-
- // Extract
- foreach (var entry in archive.Entries)
+ private async Task WriteToDirectoryAsyncInternal(
+ string destinationDirectory,
+ ExtractionOptions? options,
+ IProgress? progress,
+ CancellationToken cancellationToken
+ )
{
- cancellationToken.ThrowIfCancellationRequested();
+ // Prepare for progress reporting
+ var totalBytes = archive.TotalUncompressSize;
+ var bytesRead = 0L;
- if (entry.IsDirectory)
+ // Tracking for created directories.
+ var seenDirectories = new HashSet();
+
+ // Extract
+ foreach (var entry in archive.Entries)
{
- var dirPath = Path.Combine(
- destinationDirectory,
- entry.Key.NotNull("Entry Key is null")
- );
- if (
- Path.GetDirectoryName(dirPath + "/") is { } parentDirectory
- && seenDirectories.Add(dirPath)
- )
+ cancellationToken.ThrowIfCancellationRequested();
+
+ if (entry.IsDirectory)
{
- Directory.CreateDirectory(parentDirectory);
+ var dirPath = Path.Combine(
+ destinationDirectory,
+ entry.Key.NotNull("Entry Key is null")
+ );
+ if (
+ Path.GetDirectoryName(dirPath + "/") is { } parentDirectory
+ && seenDirectories.Add(dirPath)
+ )
+ {
+ Directory.CreateDirectory(parentDirectory);
+ }
+ continue;
}
- continue;
+
+ // Use the entry's WriteToDirectoryAsync method which respects ExtractionOptions
+ await entry
+ .WriteToDirectoryAsync(destinationDirectory, options, cancellationToken)
+ .ConfigureAwait(false);
+
+ // Update progress
+ bytesRead += entry.Size;
+ progress?.Report(
+ new ProgressReport(entry.Key ?? string.Empty, bytesRead, totalBytes)
+ );
}
-
- // Use the entry's WriteToDirectoryAsync method which respects ExtractionOptions
- await entry
- .WriteToDirectoryAsync(destinationDirectory, options, cancellationToken)
- .ConfigureAwait(false);
-
- // Update progress
- bytesRead += entry.Size;
- progress?.Report(new ProgressReport(entry.Key ?? string.Empty, bytesRead, totalBytes));
}
}
}