diff --git a/src/SharpCompress/Archives/IArchiveEntryExtensions.cs b/src/SharpCompress/Archives/IArchiveEntryExtensions.cs index 1db96e3e..acf340ed 100644 --- a/src/SharpCompress/Archives/IArchiveEntryExtensions.cs +++ b/src/SharpCompress/Archives/IArchiveEntryExtensions.cs @@ -3,6 +3,7 @@ using System.IO; using System.Threading; using System.Threading.Tasks; using SharpCompress.Common; +using SharpCompress.IO; namespace SharpCompress.Archives; @@ -28,26 +29,8 @@ public static class IArchiveEntryExtensions } using var entryStream = archiveEntry.OpenEntryStream(); - - if (progress is null) - { - entryStream.CopyTo(streamToWriteTo); - } - else - { - var entryPath = archiveEntry.Key ?? string.Empty; - long? totalBytes = GetEntrySizeSafe(archiveEntry); - long transferred = 0; - - var buffer = new byte[BufferSize]; - int bytesRead; - while ((bytesRead = entryStream.Read(buffer, 0, buffer.Length)) > 0) - { - streamToWriteTo.Write(buffer, 0, bytesRead); - transferred += bytesRead; - progress.Report(new ProgressReport(entryPath, transferred, totalBytes)); - } - } + var sourceStream = WrapWithProgress(entryStream, archiveEntry, progress); + sourceStream.CopyTo(streamToWriteTo, BufferSize); } /// @@ -70,36 +53,26 @@ public static class IArchiveEntryExtensions } using var entryStream = archiveEntry.OpenEntryStream(); + var sourceStream = WrapWithProgress(entryStream, archiveEntry, progress); + await sourceStream + .CopyToAsync(streamToWriteTo, BufferSize, cancellationToken) + .ConfigureAwait(false); + } + private static Stream WrapWithProgress( + Stream source, + IArchiveEntry entry, + IProgress? progress + ) + { if (progress is null) { - await entryStream - .CopyToAsync(streamToWriteTo, BufferSize, cancellationToken) - .ConfigureAwait(false); + return source; } - else - { - var entryPath = archiveEntry.Key ?? string.Empty; - long? totalBytes = GetEntrySizeSafe(archiveEntry); - long transferred = 0; - var buffer = new byte[BufferSize]; - int bytesRead; - while ( - ( - bytesRead = await entryStream - .ReadAsync(buffer, 0, buffer.Length, cancellationToken) - .ConfigureAwait(false) - ) > 0 - ) - { - await streamToWriteTo - .WriteAsync(buffer, 0, bytesRead, cancellationToken) - .ConfigureAwait(false); - transferred += bytesRead; - progress.Report(new ProgressReport(entryPath, transferred, totalBytes)); - } - } + var entryPath = entry.Key ?? string.Empty; + long? totalBytes = GetEntrySizeSafe(entry); + return new ProgressReportingStream(source, progress, entryPath, totalBytes, leaveOpen: true); } private static long? GetEntrySizeSafe(IArchiveEntry entry) diff --git a/src/SharpCompress/Readers/AbstractReader.cs b/src/SharpCompress/Readers/AbstractReader.cs index b20abcfd..42223063 100644 --- a/src/SharpCompress/Readers/AbstractReader.cs +++ b/src/SharpCompress/Readers/AbstractReader.cs @@ -261,22 +261,36 @@ public abstract class AbstractReader : IReader internal void Write(Stream writeStream) { using Stream s = OpenEntryStream(); - TransferWithProgress(s, writeStream, Entry); + var sourceStream = WrapWithProgress(s, Entry); + sourceStream.CopyTo(writeStream, 81920); } internal async Task WriteAsync(Stream writeStream, CancellationToken cancellationToken) { #if NETFRAMEWORK || NETSTANDARD2_0 using Stream s = OpenEntryStream(); - await TransferWithProgressAsync(s, writeStream, Entry, cancellationToken) - .ConfigureAwait(false); + var sourceStream = WrapWithProgress(s, Entry); + await sourceStream.CopyToAsync(writeStream, 81920, cancellationToken).ConfigureAwait(false); #else await using Stream s = OpenEntryStream(); - await TransferWithProgressAsync(s, writeStream, Entry, cancellationToken) - .ConfigureAwait(false); + var sourceStream = WrapWithProgress(s, Entry); + await sourceStream.CopyToAsync(writeStream, 81920, cancellationToken).ConfigureAwait(false); #endif } + private Stream WrapWithProgress(Stream source, Entry entry) + { + var progress = Options.Progress; + if (progress is null) + { + return source; + } + + var entryPath = entry.Key ?? string.Empty; + long? totalBytes = GetEntrySizeSafe(entry); + return new ProgressReportingStream(source, progress, entryPath, totalBytes, leaveOpen: true); + } + private static long? GetEntrySizeSafe(Entry entry) { try @@ -292,53 +306,6 @@ public abstract class AbstractReader : IReader } } - private void TransferWithProgress(Stream source, Stream destination, Entry entry) - { - var progress = Options.Progress; - var entryPath = entry.Key ?? string.Empty; - long? totalBytes = GetEntrySizeSafe(entry); - long transferred = 0; - - var buffer = new byte[81920]; - int bytesRead; - while ((bytesRead = source.Read(buffer, 0, buffer.Length)) > 0) - { - destination.Write(buffer, 0, bytesRead); - transferred += bytesRead; - progress?.Report(new ProgressReport(entryPath, transferred, totalBytes)); - } - } - - private async Task TransferWithProgressAsync( - Stream source, - Stream destination, - Entry entry, - CancellationToken cancellationToken - ) - { - var progress = Options.Progress; - var entryPath = entry.Key ?? string.Empty; - long? totalBytes = GetEntrySizeSafe(entry); - long transferred = 0; - - var buffer = new byte[81920]; - int bytesRead; - while ( - ( - bytesRead = await source - .ReadAsync(buffer, 0, buffer.Length, cancellationToken) - .ConfigureAwait(false) - ) > 0 - ) - { - await destination - .WriteAsync(buffer, 0, bytesRead, cancellationToken) - .ConfigureAwait(false); - transferred += bytesRead; - progress?.Report(new ProgressReport(entryPath, transferred, totalBytes)); - } - } - public EntryStream OpenEntryStream() { if (_wroteCurrentEntry)