diff --git a/src/SharpCompress/Archives/ArchiveFactory.cs b/src/SharpCompress/Archives/ArchiveFactory.cs index c979b700..b22f56b1 100644 --- a/src/SharpCompress/Archives/ArchiveFactory.cs +++ b/src/SharpCompress/Archives/ArchiveFactory.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Threading.Tasks; using SharpCompress.Common; using SharpCompress.Factories; using SharpCompress.IO; @@ -116,14 +117,14 @@ public static class ArchiveFactory /// /// Extract to specific directory, retaining filename /// - public static void WriteToDirectory( + public static async Task WriteToDirectoryAsync( string sourceArchive, string destinationDirectory, ExtractionOptions? options = null ) { using var archive = Open(sourceArchive); - archive.WriteToDirectory(destinationDirectory, options); + await archive.WriteToDirectoryAsync(destinationDirectory, options); } private static T FindFactory(FileInfo finfo) diff --git a/src/SharpCompress/Archives/IArchiveEntryExtensions.cs b/src/SharpCompress/Archives/IArchiveEntryExtensions.cs index 3d1daa1a..d820020d 100644 --- a/src/SharpCompress/Archives/IArchiveEntryExtensions.cs +++ b/src/SharpCompress/Archives/IArchiveEntryExtensions.cs @@ -1,4 +1,5 @@ using System.IO; +using System.Threading.Tasks; using SharpCompress.Common; using SharpCompress.IO; @@ -6,7 +7,7 @@ namespace SharpCompress.Archives; public static class IArchiveEntryExtensions { - public static void WriteTo(this IArchiveEntry archiveEntry, Stream streamToWriteTo) + public static async Task WriteToAsync(this IArchiveEntry archiveEntry, Stream streamToWriteTo) { if (archiveEntry.IsDirectory) { @@ -21,11 +22,11 @@ public static class IArchiveEntryExtensions archiveEntry.Size, archiveEntry.CompressedSize ); - var entryStream = archiveEntry.OpenEntryStream(); + var entryStream = await archiveEntry.OpenEntryStreamAsync(); using (entryStream) { using Stream s = new ListeningStream(streamListener, entryStream); - s.TransferTo(streamToWriteTo); + await s.TransferToAsync(streamToWriteTo); } streamListener.FireEntryExtractionEnd(archiveEntry); } @@ -33,34 +34,34 @@ public static class IArchiveEntryExtensions /// /// Extract to specific directory, retaining filename /// - public static void WriteToDirectory( + public static async Task WriteEntryToDirectoryAsync( this IArchiveEntry entry, string destinationDirectory, ExtractionOptions? options = null ) => - ExtractionMethods.WriteEntryToDirectory( + await ExtractionMethods.WriteEntryToDirectoryAsync( entry, destinationDirectory, options, - entry.WriteToFile + entry.WriteToFileAsync ); /// /// Extract to specific file /// - public static void WriteToFile( + public static Task WriteToFileAsync( this IArchiveEntry entry, string destinationFileName, ExtractionOptions? options = null ) => - ExtractionMethods.WriteEntryToFile( + ExtractionMethods.WriteEntryToFileAsync( entry, destinationFileName, options, - (x, fm) => + async (x, fm) => { using var fs = File.Open(destinationFileName, fm); - entry.WriteTo(fs); + await entry.WriteToAsync(fs); } ); } diff --git a/src/SharpCompress/Archives/IArchiveExtensions.cs b/src/SharpCompress/Archives/IArchiveExtensions.cs index 337e4ccc..651c68e3 100644 --- a/src/SharpCompress/Archives/IArchiveExtensions.cs +++ b/src/SharpCompress/Archives/IArchiveExtensions.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; +using System.Threading.Tasks; using SharpCompress.Common; using SharpCompress.Readers; @@ -13,14 +14,14 @@ public static class IArchiveExtensions /// /// Extract to specific directory, retaining filename /// - public static void WriteToDirectory( + public static async Task WriteToDirectoryAsync( this IArchive archive, string destinationDirectory, ExtractionOptions? options = null ) { using var reader = archive.ExtractAllEntries(); - reader.WriteAllToDirectory(destinationDirectory, options); + await reader.WriteAllToDirectoryAsync(destinationDirectory, options); } /// @@ -30,7 +31,7 @@ public static class IArchiveExtensions /// The folder to extract into. /// Optional progress report callback. /// Optional cancellation token. - public static void ExtractToDirectory( + public static async Task ExtractToDirectory( this IArchive archive, string destination, Action? progressReport = null, @@ -46,7 +47,7 @@ public static class IArchiveExtensions // Extract var entries = archive.ExtractAllEntries(); - while (entries.MoveToNextEntry()) + while (await entries.MoveToNextEntryAsync()) { cancellationToken.ThrowIfCancellationRequested(); @@ -77,7 +78,7 @@ public static class IArchiveExtensions // Write file using var fs = File.OpenWrite(path); - entries.WriteEntryTo(fs); + await entries.WriteEntryToAsync(fs); // Update progress bytesRead += entry.Size; diff --git a/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs b/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs index 323f07ac..5ff6d902 100644 --- a/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs +++ b/src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Threading.Tasks; using SharpCompress.Common; using SharpCompress.Common.SevenZip; using SharpCompress.Compressors.LZMA.Utilites; @@ -253,8 +254,8 @@ public class SevenZipArchive : AbstractArchive - CreateEntryStream( + protected override Task GetEntryStreamAsync() => + CreateEntryStreamAsync( new ReadOnlySubStream( _currentStream.NotNull("currentStream is not null"), _currentItem?.Size ?? 0 diff --git a/src/SharpCompress/Common/ExtractionMethods.cs b/src/SharpCompress/Common/ExtractionMethods.cs index 799d47b3..98c44756 100644 --- a/src/SharpCompress/Common/ExtractionMethods.cs +++ b/src/SharpCompress/Common/ExtractionMethods.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Threading.Tasks; namespace SharpCompress.Common; @@ -8,11 +9,11 @@ internal static class ExtractionMethods /// /// Extract to specific directory, retaining filename /// - public static void WriteEntryToDirectory( + public static async Task WriteEntryToDirectoryAsync( IEntry entry, string destinationDirectory, ExtractionOptions? options, - Action write + Func write ) { string destinationFileName; @@ -77,7 +78,7 @@ internal static class ExtractionMethods "Entry is trying to write a file outside of the destination directory." ); } - write(destinationFileName, options); + await write(destinationFileName, options); } else if (options.ExtractFullPath && !Directory.Exists(destinationFileName)) { @@ -85,11 +86,11 @@ internal static class ExtractionMethods } } - public static void WriteEntryToFile( + public static async Task WriteEntryToFileAsync( IEntry entry, string destinationFileName, ExtractionOptions? options, - Action openAndWrite + Func openAndWrite ) { if (entry.LinkTarget != null) @@ -112,7 +113,7 @@ internal static class ExtractionMethods fm = FileMode.CreateNew; } - openAndWrite(destinationFileName, fm); + await openAndWrite(destinationFileName, fm); entry.PreserveExtractionOptions(destinationFileName, options); } } diff --git a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack_cpp_async.cs b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack_cpp_async.cs index 2cdec365..c3fd3557 100644 --- a/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack_cpp_async.cs +++ b/src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack_cpp_async.cs @@ -1,4 +1,5 @@ #if !NETSTANDARD2_0 && !NETFRAMEWORK +#nullable disable using System; using SharpCompress.Common; diff --git a/src/SharpCompress/Readers/IReaderExtensions.cs b/src/SharpCompress/Readers/IReaderExtensions.cs index 0e51d72a..c71ad6f3 100644 --- a/src/SharpCompress/Readers/IReaderExtensions.cs +++ b/src/SharpCompress/Readers/IReaderExtensions.cs @@ -1,68 +1,69 @@ using System.IO; +using System.Threading.Tasks; using SharpCompress.Common; namespace SharpCompress.Readers; public static class IReaderExtensions { - public static void WriteEntryTo(this IReader reader, string filePath) + public static async Task WriteEntryToAsync(this IReader reader, string filePath) { using Stream stream = File.Open(filePath, FileMode.Create, FileAccess.Write); - reader.WriteEntryTo(stream); + await reader.WriteEntryToAsync(stream); } - public static void WriteEntryTo(this IReader reader, FileInfo filePath) + public static async Task WriteEntryToAsync(this IReader reader, FileInfo filePath) { using Stream stream = filePath.Open(FileMode.Create); - reader.WriteEntryTo(stream); + await reader.WriteEntryToAsync(stream); } /// /// Extract all remaining unread entries to specific directory, retaining filename /// - public static void WriteAllToDirectory( + public static async Task WriteAllToDirectoryAsync( this IReader reader, string destinationDirectory, ExtractionOptions? options = null ) { - while (reader.MoveToNextEntry()) + while (await reader.MoveToNextEntryAsync()) { - reader.WriteEntryToDirectory(destinationDirectory, options); + await reader.WriteEntryToDirectoryAsync(destinationDirectory, options); } } /// /// Extract to specific directory, retaining filename /// - public static void WriteEntryToDirectory( + public static async Task WriteEntryToDirectoryAsync( this IReader reader, string destinationDirectory, ExtractionOptions? options = null ) => - ExtractionMethods.WriteEntryToDirectory( + await ExtractionMethods.WriteEntryToDirectoryAsync( reader.Entry, destinationDirectory, options, - reader.WriteEntryToFile + reader.WriteEntryToFileAsync ); /// /// Extract to specific file /// - public static void WriteEntryToFile( + public static async Task WriteEntryToFileAsync( this IReader reader, string destinationFileName, ExtractionOptions? options = null ) => - ExtractionMethods.WriteEntryToFile( + await ExtractionMethods.WriteEntryToFileAsync( reader.Entry, destinationFileName, options, - (x, fm) => + async (x, fm) => { using var fs = File.Open(destinationFileName, fm); - reader.WriteEntryTo(fs); + await reader.WriteEntryToAsync(fs); } ); } diff --git a/src/SharpCompress/Utility.cs b/src/SharpCompress/Utility.cs index cc2cb532..811cd43c 100644 --- a/src/SharpCompress/Utility.cs +++ b/src/SharpCompress/Utility.cs @@ -304,6 +304,26 @@ internal static class Utility } } + public static async Task TransferToAsync(this Stream source, Stream destination) + { + var array = GetTransferByteArray(); + try + { + long total = 0; + int count; + while ((count = await source.ReadAsync(array, 0, array.Length)) != 0) + { + await destination.WriteAsync(array, 0, count); + total += count; + } + return total; + } + finally + { + ArrayPool.Shared.Return(array); + } + } + public static long TransferTo(this Stream source, Stream destination, long maxLength) { var array = GetTransferByteArray(); @@ -365,6 +385,7 @@ internal static class Utility } } + private static bool ReadTransferBlock(Stream source, byte[] array, out int count) => (count = source.Read(array, 0, array.Length)) != 0;