From 467fc2d03dc4f0710761d17e6728c68b73b65d79 Mon Sep 17 00:00:00 2001 From: Anders Gardebring Date: Thu, 20 Apr 2017 11:45:53 +0200 Subject: [PATCH 1/6] Add new feature to allow injection of an action into the extraction process. This allows for showing or logging progress of the extraction process, especially useful for large files that might take a long time to extract. --- .../Archives/IArchiveEntryExtensions.cs | 7 ++++--- src/SharpCompress/Readers/AbstractReader.cs | 11 +++++----- src/SharpCompress/Readers/IReader.cs | 3 ++- .../Readers/IReaderExtensions.cs | 21 +++++++++++++------ src/SharpCompress/Utility.cs | 5 ++++- src/SharpCompress/Writers/AbstractWriter.cs | 2 +- src/SharpCompress/Writers/GZip/GZipWriter.cs | 4 ++-- src/SharpCompress/Writers/IWriter.cs | 2 +- src/SharpCompress/Writers/Tar/TarWriter.cs | 8 +++---- src/SharpCompress/Writers/Zip/ZipWriter.cs | 8 +++---- 10 files changed, 42 insertions(+), 29 deletions(-) diff --git a/src/SharpCompress/Archives/IArchiveEntryExtensions.cs b/src/SharpCompress/Archives/IArchiveEntryExtensions.cs index f4f8cb6b5..878ad797a 100644 --- a/src/SharpCompress/Archives/IArchiveEntryExtensions.cs +++ b/src/SharpCompress/Archives/IArchiveEntryExtensions.cs @@ -1,4 +1,5 @@ -using System.IO; +using System; +using System.IO; using SharpCompress.Common; using SharpCompress.IO; using SharpCompress.Readers; @@ -7,7 +8,7 @@ namespace SharpCompress.Archives { public static class IArchiveEntryExtensions { - public static void WriteTo(this IArchiveEntry archiveEntry, Stream streamToWriteTo) + public static void WriteTo(this IArchiveEntry archiveEntry, Stream streamToWriteTo, Action partTransferredAction = null) { if (archiveEntry.Archive.Type == ArchiveType.Rar && archiveEntry.Archive.IsSolid) { @@ -32,7 +33,7 @@ public static void WriteTo(this IArchiveEntry archiveEntry, Stream streamToWrite { using (Stream s = new ListeningStream(streamListener, entryStream)) { - s.TransferTo(streamToWriteTo); + s.TransferTo(streamToWriteTo, partTransferredAction); } } streamListener.FireEntryExtractionEnd(archiveEntry); diff --git a/src/SharpCompress/Readers/AbstractReader.cs b/src/SharpCompress/Readers/AbstractReader.cs index 380e8df5a..a055c17fc 100644 --- a/src/SharpCompress/Readers/AbstractReader.cs +++ b/src/SharpCompress/Readers/AbstractReader.cs @@ -167,7 +167,7 @@ private void Skip() } } - public void WriteEntryTo(Stream writableStream) + public void WriteEntryTo(Stream writableStream, Action partTransferredAction = null) { if (wroteCurrentEntry) { @@ -175,22 +175,21 @@ public void WriteEntryTo(Stream writableStream) } if ((writableStream == null) || (!writableStream.CanWrite)) { - throw new ArgumentNullException( - "A writable Stream was required. Use Cancel if that was intended."); + throw new ArgumentNullException("A writable Stream was required. Use Cancel if that was intended."); } var streamListener = this as IReaderExtractionListener; streamListener.FireEntryExtractionBegin(Entry); - Write(writableStream); + Write(writableStream, partTransferredAction); streamListener.FireEntryExtractionEnd(Entry); wroteCurrentEntry = true; } - internal void Write(Stream writeStream) + internal void Write(Stream writeStream, Action partTransferredAction = null) { using (Stream s = OpenEntryStream()) { - s.TransferTo(writeStream); + s.TransferTo(writeStream, partTransferredAction); } } diff --git a/src/SharpCompress/Readers/IReader.cs b/src/SharpCompress/Readers/IReader.cs index 0df03177a..6b1a78184 100644 --- a/src/SharpCompress/Readers/IReader.cs +++ b/src/SharpCompress/Readers/IReader.cs @@ -20,7 +20,8 @@ public interface IReader : IDisposable /// Decompresses the current entry to the stream. This cannot be called twice for the current entry. /// /// - void WriteEntryTo(Stream writableStream); + /// + void WriteEntryTo(Stream writableStream, Action partTransferredAction = null); bool Cancelled { get; } void Cancel(); diff --git a/src/SharpCompress/Readers/IReaderExtensions.cs b/src/SharpCompress/Readers/IReaderExtensions.cs index 4100a6072..2fdeb1d90 100644 --- a/src/SharpCompress/Readers/IReaderExtensions.cs +++ b/src/SharpCompress/Readers/IReaderExtensions.cs @@ -1,4 +1,5 @@ #if !NO_FILE +using System; using System.IO; using SharpCompress.Common; #endif @@ -39,8 +40,12 @@ public static void WriteAllToDirectory(this IReader reader, string destinationDi /// /// Extract to specific directory, retaining filename /// - public static void WriteEntryToDirectory(this IReader reader, string destinationDirectory, - ExtractionOptions options = null) + public static void WriteEntryToDirectory( + this IReader reader, + string destinationDirectory, + ExtractionOptions options = null, + Action partTransferredAction = null + ) { string destinationFileName = string.Empty; string file = Path.GetFileName(reader.Entry.Key); @@ -66,7 +71,7 @@ public static void WriteEntryToDirectory(this IReader reader, string destination if (!reader.Entry.IsDirectory) { - reader.WriteEntryToFile(destinationFileName, options); + reader.WriteEntryToFile(destinationFileName, options, partTransferredAction); } else if (options.ExtractFullPath && !Directory.Exists(destinationFileName)) { @@ -77,8 +82,12 @@ public static void WriteEntryToDirectory(this IReader reader, string destination /// /// Extract to specific file /// - public static void WriteEntryToFile(this IReader reader, string destinationFileName, - ExtractionOptions options = null) + public static void WriteEntryToFile( + this IReader reader, + string destinationFileName, + ExtractionOptions options = null, + Action partTransferredAction = null + ) { FileMode fm = FileMode.Create; options = options ?? new ExtractionOptions() @@ -92,7 +101,7 @@ public static void WriteEntryToFile(this IReader reader, string destinationFileN } using (FileStream fs = File.Open(destinationFileName, fm)) { - reader.WriteEntryTo(fs); + reader.WriteEntryTo(fs, partTransferredAction); //using (Stream s = reader.OpenEntryStream()) //{ // s.TransferTo(fs); diff --git a/src/SharpCompress/Utility.cs b/src/SharpCompress/Utility.cs index 451075f38..253e0e9d3 100644 --- a/src/SharpCompress/Utility.cs +++ b/src/SharpCompress/Utility.cs @@ -229,15 +229,18 @@ public static DateTime DosDateToDateTime(Int32 iTime) return DosDateToDateTime((UInt32)iTime); } - public static long TransferTo(this Stream source, Stream destination) + public static long TransferTo(this Stream source, Stream destination, Action partTransferredAction = null) { byte[] array = new byte[81920]; int count; + var iterations = 0; long total = 0; while ((count = source.Read(array, 0, array.Length)) != 0) { total += count; destination.Write(array, 0, count); + iterations++; + partTransferredAction?.Invoke(total, iterations); } return total; } diff --git a/src/SharpCompress/Writers/AbstractWriter.cs b/src/SharpCompress/Writers/AbstractWriter.cs index dde6892a3..79f880b94 100644 --- a/src/SharpCompress/Writers/AbstractWriter.cs +++ b/src/SharpCompress/Writers/AbstractWriter.cs @@ -24,7 +24,7 @@ protected void InitalizeStream(Stream stream, bool closeStream) public ArchiveType WriterType { get; } - public abstract void Write(string filename, Stream source, DateTime? modificationTime); + public abstract void Write(string filename, Stream source, DateTime? modificationTime, Action partTransferredAction = null); protected virtual void Dispose(bool isDisposing) { diff --git a/src/SharpCompress/Writers/GZip/GZipWriter.cs b/src/SharpCompress/Writers/GZip/GZipWriter.cs index d9ef3562b..48b88a290 100644 --- a/src/SharpCompress/Writers/GZip/GZipWriter.cs +++ b/src/SharpCompress/Writers/GZip/GZipWriter.cs @@ -26,7 +26,7 @@ protected override void Dispose(bool isDisposing) base.Dispose(isDisposing); } - public override void Write(string filename, Stream source, DateTime? modificationTime) + public override void Write(string filename, Stream source, DateTime? modificationTime, Action partTransferredAction = null) { if (wroteToStream) { @@ -35,7 +35,7 @@ public override void Write(string filename, Stream source, DateTime? modificatio GZipStream stream = OutputStream as GZipStream; stream.FileName = filename; stream.LastModified = modificationTime; - source.TransferTo(stream); + source.TransferTo(stream, partTransferredAction); wroteToStream = true; } } diff --git a/src/SharpCompress/Writers/IWriter.cs b/src/SharpCompress/Writers/IWriter.cs index a15225bff..d55e8b74a 100644 --- a/src/SharpCompress/Writers/IWriter.cs +++ b/src/SharpCompress/Writers/IWriter.cs @@ -7,6 +7,6 @@ namespace SharpCompress.Writers public interface IWriter : IDisposable { ArchiveType WriterType { get; } - void Write(string filename, Stream source, DateTime? modificationTime); + void Write(string filename, Stream source, DateTime? modificationTime, Action partTransferredAction = null); } } \ No newline at end of file diff --git a/src/SharpCompress/Writers/Tar/TarWriter.cs b/src/SharpCompress/Writers/Tar/TarWriter.cs index 0dbdb0a2b..552b0c938 100644 --- a/src/SharpCompress/Writers/Tar/TarWriter.cs +++ b/src/SharpCompress/Writers/Tar/TarWriter.cs @@ -39,9 +39,9 @@ public TarWriter(Stream destination, WriterOptions options) InitalizeStream(destination, !options.LeaveStreamOpen); } - public override void Write(string filename, Stream source, DateTime? modificationTime) + public override void Write(string filename, Stream source, DateTime? modificationTime, Action partTransferredAction = null) { - Write(filename, source, modificationTime, null); + Write(filename, source, modificationTime, null, partTransferredAction); } private string NormalizeFilename(string filename) @@ -57,7 +57,7 @@ private string NormalizeFilename(string filename) return filename.Trim('/'); } - public void Write(string filename, Stream source, DateTime? modificationTime, long? size) + public void Write(string filename, Stream source, DateTime? modificationTime, long? size, Action partTransferredAction = null) { if (!source.CanSeek && size == null) { @@ -71,7 +71,7 @@ public void Write(string filename, Stream source, DateTime? modificationTime, lo header.Name = NormalizeFilename(filename); header.Size = realSize; header.Write(OutputStream); - size = source.TransferTo(OutputStream); + size = source.TransferTo(OutputStream, partTransferredAction); PadTo512(size.Value, false); } diff --git a/src/SharpCompress/Writers/Zip/ZipWriter.cs b/src/SharpCompress/Writers/Zip/ZipWriter.cs index e1a001b5e..96efa0b65 100644 --- a/src/SharpCompress/Writers/Zip/ZipWriter.cs +++ b/src/SharpCompress/Writers/Zip/ZipWriter.cs @@ -90,19 +90,19 @@ private static ZipCompressionMethod ToZipCompressionMethod(CompressionType compr } } - public override void Write(string entryPath, Stream source, DateTime? modificationTime) + public override void Write(string entryPath, Stream source, DateTime? modificationTime, Action partTransferredAction = null) { Write(entryPath, source, new ZipWriterEntryOptions() { ModificationDateTime = modificationTime - }); + }, partTransferredAction); } - public void Write(string entryPath, Stream source, ZipWriterEntryOptions zipWriterEntryOptions) + public void Write(string entryPath, Stream source, ZipWriterEntryOptions zipWriterEntryOptions, Action partTransferredAction = null) { using (Stream output = WriteToStream(entryPath, zipWriterEntryOptions)) { - source.TransferTo(output); + source.TransferTo(output, partTransferredAction); } } From b8ef1ecafcf61f80d08c5a4678cb4f78370b4e2c Mon Sep 17 00:00:00 2001 From: Anders Gardebring Date: Mon, 24 Apr 2017 10:22:49 +0200 Subject: [PATCH 2/6] Revert "Add new feature to allow injection of an action into the extraction process. This allows for showing or logging progress of the extraction process, especially useful for large files that might take a long time to extract." This reverts commit 467fc2d03dc4f0710761d17e6728c68b73b65d79. --- .../Archives/IArchiveEntryExtensions.cs | 7 +++---- src/SharpCompress/Readers/AbstractReader.cs | 11 +++++----- src/SharpCompress/Readers/IReader.cs | 3 +-- .../Readers/IReaderExtensions.cs | 21 ++++++------------- src/SharpCompress/Utility.cs | 5 +---- src/SharpCompress/Writers/AbstractWriter.cs | 2 +- src/SharpCompress/Writers/GZip/GZipWriter.cs | 4 ++-- src/SharpCompress/Writers/IWriter.cs | 2 +- src/SharpCompress/Writers/Tar/TarWriter.cs | 8 +++---- src/SharpCompress/Writers/Zip/ZipWriter.cs | 8 +++---- 10 files changed, 29 insertions(+), 42 deletions(-) diff --git a/src/SharpCompress/Archives/IArchiveEntryExtensions.cs b/src/SharpCompress/Archives/IArchiveEntryExtensions.cs index 878ad797a..f4f8cb6b5 100644 --- a/src/SharpCompress/Archives/IArchiveEntryExtensions.cs +++ b/src/SharpCompress/Archives/IArchiveEntryExtensions.cs @@ -1,5 +1,4 @@ -using System; -using System.IO; +using System.IO; using SharpCompress.Common; using SharpCompress.IO; using SharpCompress.Readers; @@ -8,7 +7,7 @@ namespace SharpCompress.Archives { public static class IArchiveEntryExtensions { - public static void WriteTo(this IArchiveEntry archiveEntry, Stream streamToWriteTo, Action partTransferredAction = null) + public static void WriteTo(this IArchiveEntry archiveEntry, Stream streamToWriteTo) { if (archiveEntry.Archive.Type == ArchiveType.Rar && archiveEntry.Archive.IsSolid) { @@ -33,7 +32,7 @@ public static void WriteTo(this IArchiveEntry archiveEntry, Stream streamToWrite { using (Stream s = new ListeningStream(streamListener, entryStream)) { - s.TransferTo(streamToWriteTo, partTransferredAction); + s.TransferTo(streamToWriteTo); } } streamListener.FireEntryExtractionEnd(archiveEntry); diff --git a/src/SharpCompress/Readers/AbstractReader.cs b/src/SharpCompress/Readers/AbstractReader.cs index a055c17fc..380e8df5a 100644 --- a/src/SharpCompress/Readers/AbstractReader.cs +++ b/src/SharpCompress/Readers/AbstractReader.cs @@ -167,7 +167,7 @@ private void Skip() } } - public void WriteEntryTo(Stream writableStream, Action partTransferredAction = null) + public void WriteEntryTo(Stream writableStream) { if (wroteCurrentEntry) { @@ -175,21 +175,22 @@ public void WriteEntryTo(Stream writableStream, Action partTransferre } if ((writableStream == null) || (!writableStream.CanWrite)) { - throw new ArgumentNullException("A writable Stream was required. Use Cancel if that was intended."); + throw new ArgumentNullException( + "A writable Stream was required. Use Cancel if that was intended."); } var streamListener = this as IReaderExtractionListener; streamListener.FireEntryExtractionBegin(Entry); - Write(writableStream, partTransferredAction); + Write(writableStream); streamListener.FireEntryExtractionEnd(Entry); wroteCurrentEntry = true; } - internal void Write(Stream writeStream, Action partTransferredAction = null) + internal void Write(Stream writeStream) { using (Stream s = OpenEntryStream()) { - s.TransferTo(writeStream, partTransferredAction); + s.TransferTo(writeStream); } } diff --git a/src/SharpCompress/Readers/IReader.cs b/src/SharpCompress/Readers/IReader.cs index 6b1a78184..0df03177a 100644 --- a/src/SharpCompress/Readers/IReader.cs +++ b/src/SharpCompress/Readers/IReader.cs @@ -20,8 +20,7 @@ public interface IReader : IDisposable /// Decompresses the current entry to the stream. This cannot be called twice for the current entry. /// /// - /// - void WriteEntryTo(Stream writableStream, Action partTransferredAction = null); + void WriteEntryTo(Stream writableStream); bool Cancelled { get; } void Cancel(); diff --git a/src/SharpCompress/Readers/IReaderExtensions.cs b/src/SharpCompress/Readers/IReaderExtensions.cs index 2fdeb1d90..4100a6072 100644 --- a/src/SharpCompress/Readers/IReaderExtensions.cs +++ b/src/SharpCompress/Readers/IReaderExtensions.cs @@ -1,5 +1,4 @@ #if !NO_FILE -using System; using System.IO; using SharpCompress.Common; #endif @@ -40,12 +39,8 @@ public static void WriteAllToDirectory(this IReader reader, string destinationDi /// /// Extract to specific directory, retaining filename /// - public static void WriteEntryToDirectory( - this IReader reader, - string destinationDirectory, - ExtractionOptions options = null, - Action partTransferredAction = null - ) + public static void WriteEntryToDirectory(this IReader reader, string destinationDirectory, + ExtractionOptions options = null) { string destinationFileName = string.Empty; string file = Path.GetFileName(reader.Entry.Key); @@ -71,7 +66,7 @@ public static void WriteEntryToDirectory( if (!reader.Entry.IsDirectory) { - reader.WriteEntryToFile(destinationFileName, options, partTransferredAction); + reader.WriteEntryToFile(destinationFileName, options); } else if (options.ExtractFullPath && !Directory.Exists(destinationFileName)) { @@ -82,12 +77,8 @@ public static void WriteEntryToDirectory( /// /// Extract to specific file /// - public static void WriteEntryToFile( - this IReader reader, - string destinationFileName, - ExtractionOptions options = null, - Action partTransferredAction = null - ) + public static void WriteEntryToFile(this IReader reader, string destinationFileName, + ExtractionOptions options = null) { FileMode fm = FileMode.Create; options = options ?? new ExtractionOptions() @@ -101,7 +92,7 @@ public static void WriteEntryToFile( } using (FileStream fs = File.Open(destinationFileName, fm)) { - reader.WriteEntryTo(fs, partTransferredAction); + reader.WriteEntryTo(fs); //using (Stream s = reader.OpenEntryStream()) //{ // s.TransferTo(fs); diff --git a/src/SharpCompress/Utility.cs b/src/SharpCompress/Utility.cs index 253e0e9d3..451075f38 100644 --- a/src/SharpCompress/Utility.cs +++ b/src/SharpCompress/Utility.cs @@ -229,18 +229,15 @@ public static DateTime DosDateToDateTime(Int32 iTime) return DosDateToDateTime((UInt32)iTime); } - public static long TransferTo(this Stream source, Stream destination, Action partTransferredAction = null) + public static long TransferTo(this Stream source, Stream destination) { byte[] array = new byte[81920]; int count; - var iterations = 0; long total = 0; while ((count = source.Read(array, 0, array.Length)) != 0) { total += count; destination.Write(array, 0, count); - iterations++; - partTransferredAction?.Invoke(total, iterations); } return total; } diff --git a/src/SharpCompress/Writers/AbstractWriter.cs b/src/SharpCompress/Writers/AbstractWriter.cs index 79f880b94..dde6892a3 100644 --- a/src/SharpCompress/Writers/AbstractWriter.cs +++ b/src/SharpCompress/Writers/AbstractWriter.cs @@ -24,7 +24,7 @@ protected void InitalizeStream(Stream stream, bool closeStream) public ArchiveType WriterType { get; } - public abstract void Write(string filename, Stream source, DateTime? modificationTime, Action partTransferredAction = null); + public abstract void Write(string filename, Stream source, DateTime? modificationTime); protected virtual void Dispose(bool isDisposing) { diff --git a/src/SharpCompress/Writers/GZip/GZipWriter.cs b/src/SharpCompress/Writers/GZip/GZipWriter.cs index 48b88a290..d9ef3562b 100644 --- a/src/SharpCompress/Writers/GZip/GZipWriter.cs +++ b/src/SharpCompress/Writers/GZip/GZipWriter.cs @@ -26,7 +26,7 @@ protected override void Dispose(bool isDisposing) base.Dispose(isDisposing); } - public override void Write(string filename, Stream source, DateTime? modificationTime, Action partTransferredAction = null) + public override void Write(string filename, Stream source, DateTime? modificationTime) { if (wroteToStream) { @@ -35,7 +35,7 @@ public override void Write(string filename, Stream source, DateTime? modificatio GZipStream stream = OutputStream as GZipStream; stream.FileName = filename; stream.LastModified = modificationTime; - source.TransferTo(stream, partTransferredAction); + source.TransferTo(stream); wroteToStream = true; } } diff --git a/src/SharpCompress/Writers/IWriter.cs b/src/SharpCompress/Writers/IWriter.cs index d55e8b74a..a15225bff 100644 --- a/src/SharpCompress/Writers/IWriter.cs +++ b/src/SharpCompress/Writers/IWriter.cs @@ -7,6 +7,6 @@ namespace SharpCompress.Writers public interface IWriter : IDisposable { ArchiveType WriterType { get; } - void Write(string filename, Stream source, DateTime? modificationTime, Action partTransferredAction = null); + void Write(string filename, Stream source, DateTime? modificationTime); } } \ No newline at end of file diff --git a/src/SharpCompress/Writers/Tar/TarWriter.cs b/src/SharpCompress/Writers/Tar/TarWriter.cs index 552b0c938..0dbdb0a2b 100644 --- a/src/SharpCompress/Writers/Tar/TarWriter.cs +++ b/src/SharpCompress/Writers/Tar/TarWriter.cs @@ -39,9 +39,9 @@ public TarWriter(Stream destination, WriterOptions options) InitalizeStream(destination, !options.LeaveStreamOpen); } - public override void Write(string filename, Stream source, DateTime? modificationTime, Action partTransferredAction = null) + public override void Write(string filename, Stream source, DateTime? modificationTime) { - Write(filename, source, modificationTime, null, partTransferredAction); + Write(filename, source, modificationTime, null); } private string NormalizeFilename(string filename) @@ -57,7 +57,7 @@ private string NormalizeFilename(string filename) return filename.Trim('/'); } - public void Write(string filename, Stream source, DateTime? modificationTime, long? size, Action partTransferredAction = null) + public void Write(string filename, Stream source, DateTime? modificationTime, long? size) { if (!source.CanSeek && size == null) { @@ -71,7 +71,7 @@ public void Write(string filename, Stream source, DateTime? modificationTime, lo header.Name = NormalizeFilename(filename); header.Size = realSize; header.Write(OutputStream); - size = source.TransferTo(OutputStream, partTransferredAction); + size = source.TransferTo(OutputStream); PadTo512(size.Value, false); } diff --git a/src/SharpCompress/Writers/Zip/ZipWriter.cs b/src/SharpCompress/Writers/Zip/ZipWriter.cs index 96efa0b65..e1a001b5e 100644 --- a/src/SharpCompress/Writers/Zip/ZipWriter.cs +++ b/src/SharpCompress/Writers/Zip/ZipWriter.cs @@ -90,19 +90,19 @@ private static ZipCompressionMethod ToZipCompressionMethod(CompressionType compr } } - public override void Write(string entryPath, Stream source, DateTime? modificationTime, Action partTransferredAction = null) + public override void Write(string entryPath, Stream source, DateTime? modificationTime) { Write(entryPath, source, new ZipWriterEntryOptions() { ModificationDateTime = modificationTime - }, partTransferredAction); + }); } - public void Write(string entryPath, Stream source, ZipWriterEntryOptions zipWriterEntryOptions, Action partTransferredAction = null) + public void Write(string entryPath, Stream source, ZipWriterEntryOptions zipWriterEntryOptions) { using (Stream output = WriteToStream(entryPath, zipWriterEntryOptions)) { - source.TransferTo(output, partTransferredAction); + source.TransferTo(output); } } From 683d2714d0b058b570ba4cbcda3e97c2cd4968e4 Mon Sep 17 00:00:00 2001 From: Anders Gardebring Date: Mon, 24 Apr 2017 13:50:45 +0200 Subject: [PATCH 3/6] Add new event to be able to track progress of extraction of individual entry when extracting an archive. This allows for showing or logging progress of the extraction process, especially useful for large files that might take a long time to extract. --- .../Common/ReaderExtractionEventArgs.cs | 4 +++- src/SharpCompress/Readers/AbstractReader.cs | 15 +++++++++--- src/SharpCompress/Readers/IReader.cs | 1 + .../Readers/IReaderExtractionListener.cs | 1 + src/SharpCompress/Readers/ReaderProgress.cs | 24 +++++++++++++++++++ src/SharpCompress/Utility.cs | 5 +++- 6 files changed, 45 insertions(+), 5 deletions(-) create mode 100644 src/SharpCompress/Readers/ReaderProgress.cs diff --git a/src/SharpCompress/Common/ReaderExtractionEventArgs.cs b/src/SharpCompress/Common/ReaderExtractionEventArgs.cs index b33b8635e..fd11e8942 100644 --- a/src/SharpCompress/Common/ReaderExtractionEventArgs.cs +++ b/src/SharpCompress/Common/ReaderExtractionEventArgs.cs @@ -4,11 +4,13 @@ namespace SharpCompress.Common { public class ReaderExtractionEventArgs : EventArgs { - internal ReaderExtractionEventArgs(T entry) + internal ReaderExtractionEventArgs(T entry, params object[] paramList) { Item = entry; + ParamList = paramList; } public T Item { get; private set; } + public object[] ParamList { get; private set; } } } \ No newline at end of file diff --git a/src/SharpCompress/Readers/AbstractReader.cs b/src/SharpCompress/Readers/AbstractReader.cs index 380e8df5a..85289cb49 100644 --- a/src/SharpCompress/Readers/AbstractReader.cs +++ b/src/SharpCompress/Readers/AbstractReader.cs @@ -19,6 +19,7 @@ public abstract class AbstractReader : IReader, IReaderExtracti public event EventHandler> EntryExtractionBegin; public event EventHandler> EntryExtractionEnd; + public event EventHandler> EntryExtractionProgress; public event EventHandler CompressedBytesRead; public event EventHandler FilePartExtractionBegin; @@ -181,16 +182,16 @@ public void WriteEntryTo(Stream writableStream) var streamListener = this as IReaderExtractionListener; streamListener.FireEntryExtractionBegin(Entry); - Write(writableStream); + Write(writableStream, streamListener); streamListener.FireEntryExtractionEnd(Entry); wroteCurrentEntry = true; } - internal void Write(Stream writeStream) + internal void Write(Stream writeStream, IReaderExtractionListener streamListener) { using (Stream s = OpenEntryStream()) { - s.TransferTo(writeStream); + s.TransferTo(writeStream, (sizeTransferred, iterations) => streamListener.FireEntryExtractionProgress(Entry, sizeTransferred, iterations)); } } @@ -255,6 +256,14 @@ void IReaderExtractionListener.FireEntryExtractionBegin(Entry entry) } } + void IReaderExtractionListener.FireEntryExtractionProgress(Entry entry, long bytesTransferred, int iterations) + { + if (EntryExtractionProgress != null) + { + EntryExtractionProgress(this, new ReaderExtractionEventArgs(entry, new ReaderProgress(entry, bytesTransferred, iterations))); + } + } + void IReaderExtractionListener.FireEntryExtractionEnd(Entry entry) { if (EntryExtractionEnd != null) diff --git a/src/SharpCompress/Readers/IReader.cs b/src/SharpCompress/Readers/IReader.cs index 0df03177a..1f8dbdab1 100644 --- a/src/SharpCompress/Readers/IReader.cs +++ b/src/SharpCompress/Readers/IReader.cs @@ -8,6 +8,7 @@ public interface IReader : IDisposable { event EventHandler> EntryExtractionBegin; event EventHandler> EntryExtractionEnd; + event EventHandler> EntryExtractionProgress; event EventHandler CompressedBytesRead; event EventHandler FilePartExtractionBegin; diff --git a/src/SharpCompress/Readers/IReaderExtractionListener.cs b/src/SharpCompress/Readers/IReaderExtractionListener.cs index 226b09448..e00d9801f 100644 --- a/src/SharpCompress/Readers/IReaderExtractionListener.cs +++ b/src/SharpCompress/Readers/IReaderExtractionListener.cs @@ -7,5 +7,6 @@ internal interface IReaderExtractionListener : IExtractionListener // void EnsureEntriesLoaded(); void FireEntryExtractionBegin(Entry entry); void FireEntryExtractionEnd(Entry entry); + void FireEntryExtractionProgress(Entry entry, long sizeTransferred, int iterations); } } \ No newline at end of file diff --git a/src/SharpCompress/Readers/ReaderProgress.cs b/src/SharpCompress/Readers/ReaderProgress.cs new file mode 100644 index 000000000..94feb74dc --- /dev/null +++ b/src/SharpCompress/Readers/ReaderProgress.cs @@ -0,0 +1,24 @@ + + +using System; +using SharpCompress.Common; + +namespace SharpCompress.Readers +{ + public class ReaderProgress + { + private readonly IEntry _entry; + public long BytesTransferred { get; private set; } + public int Iterations { get; private set; } + + public int PercentageRead => (int)Math.Round(PercentageReadExact); + public double PercentageReadExact => (float)BytesTransferred / _entry.Size * 100; + + public ReaderProgress(IEntry entry, long bytesTransferred, int iterations) + { + _entry = entry; + BytesTransferred = bytesTransferred; + Iterations = iterations; + } + } +} diff --git a/src/SharpCompress/Utility.cs b/src/SharpCompress/Utility.cs index 451075f38..009528469 100644 --- a/src/SharpCompress/Utility.cs +++ b/src/SharpCompress/Utility.cs @@ -229,15 +229,18 @@ public static DateTime DosDateToDateTime(Int32 iTime) return DosDateToDateTime((UInt32)iTime); } - public static long TransferTo(this Stream source, Stream destination) + public static long TransferTo(this Stream source, Stream destination, Action action = null) { byte[] array = new byte[81920]; int count; + var iterations = 0; long total = 0; while ((count = source.Read(array, 0, array.Length)) != 0) { total += count; destination.Write(array, 0, count); + iterations++; + action?.Invoke(total, iterations); } return total; } From e05f9843bada5fa8ef34427a1e2d98ad610ae7bc Mon Sep 17 00:00:00 2001 From: Anders Gardebring Date: Tue, 25 Apr 2017 12:36:32 +0200 Subject: [PATCH 4/6] Use strongly typed ReaderProgress instead of object[] --- src/SharpCompress/Common/ReaderExtractionEventArgs.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/SharpCompress/Common/ReaderExtractionEventArgs.cs b/src/SharpCompress/Common/ReaderExtractionEventArgs.cs index fd11e8942..3b9ac17f5 100644 --- a/src/SharpCompress/Common/ReaderExtractionEventArgs.cs +++ b/src/SharpCompress/Common/ReaderExtractionEventArgs.cs @@ -1,16 +1,17 @@ using System; +using SharpCompress.Readers; namespace SharpCompress.Common { public class ReaderExtractionEventArgs : EventArgs { - internal ReaderExtractionEventArgs(T entry, params object[] paramList) + internal ReaderExtractionEventArgs(T entry, ReaderProgress readerProgress = null) { Item = entry; - ParamList = paramList; + ReaderProgress = readerProgress; } public T Item { get; private set; } - public object[] ParamList { get; private set; } + public ReaderProgress ReaderProgress { get; private set; } } } \ No newline at end of file From 0990b06cc9eca5372d0ab03e4df45dfe4ef9921e Mon Sep 17 00:00:00 2001 From: Anders Gardebring Date: Tue, 25 Apr 2017 12:48:56 +0200 Subject: [PATCH 5/6] Create new TransferTo method and pass Entry and IReaderExtractionListener instead of passing an action lambda. --- src/SharpCompress/Readers/AbstractReader.cs | 2 +- src/SharpCompress/Utility.cs | 32 ++++++++++++++++++--- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/SharpCompress/Readers/AbstractReader.cs b/src/SharpCompress/Readers/AbstractReader.cs index 85289cb49..ecfeeb4b9 100644 --- a/src/SharpCompress/Readers/AbstractReader.cs +++ b/src/SharpCompress/Readers/AbstractReader.cs @@ -191,7 +191,7 @@ internal void Write(Stream writeStream, IReaderExtractionListener streamListener { using (Stream s = OpenEntryStream()) { - s.TransferTo(writeStream, (sizeTransferred, iterations) => streamListener.FireEntryExtractionProgress(Entry, sizeTransferred, iterations)); + s.TransferTo(writeStream, Entry, streamListener); } } diff --git a/src/SharpCompress/Utility.cs b/src/SharpCompress/Utility.cs index 009528469..0486a5fdc 100644 --- a/src/SharpCompress/Utility.cs +++ b/src/SharpCompress/Utility.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using SharpCompress.Readers; namespace SharpCompress { @@ -229,22 +230,45 @@ public static DateTime DosDateToDateTime(Int32 iTime) return DosDateToDateTime((UInt32)iTime); } - public static long TransferTo(this Stream source, Stream destination, Action action = null) + public static long TransferTo(this Stream source, Stream destination) { - byte[] array = new byte[81920]; + byte[] array = GetTransferByteArray(); + int count; + long total = 0; + while (ReadTransferBlock(source, array, out count)) + { + total += count; + destination.Write(array, 0, count); + } + return total; + } + + public static long TransferTo(this Stream source, Stream destination, Common.Entry entry, IReaderExtractionListener readerExtractionListener) + { + byte[] array = GetTransferByteArray(); int count; var iterations = 0; long total = 0; - while ((count = source.Read(array, 0, array.Length)) != 0) + while (ReadTransferBlock(source, array, out count)) { total += count; destination.Write(array, 0, count); iterations++; - action?.Invoke(total, iterations); + readerExtractionListener.FireEntryExtractionProgress(entry, total, iterations); } return total; } + private static bool ReadTransferBlock(Stream source, byte[] array, out int count) + { + return (count = source.Read(array, 0, array.Length)) != 0; + } + + private static byte[] GetTransferByteArray() + { + return new byte[81920]; + } + public static bool ReadFully(this Stream stream, byte[] buffer) { int total = 0; From 2aa123ccd7bc8db2c8caa6f1b5c3a4bae7f79ffc Mon Sep 17 00:00:00 2001 From: Anders Gardebring Date: Tue, 25 Apr 2017 13:21:04 +0200 Subject: [PATCH 6/6] Remove begin and end events since this can now be tracked via progress instead --- src/SharpCompress/Readers/AbstractReader.cs | 29 ++++--------------- src/SharpCompress/Readers/IReader.cs | 2 -- .../Readers/IReaderExtractionListener.cs | 3 -- 3 files changed, 6 insertions(+), 28 deletions(-) diff --git a/src/SharpCompress/Readers/AbstractReader.cs b/src/SharpCompress/Readers/AbstractReader.cs index ecfeeb4b9..af0cbdeb5 100644 --- a/src/SharpCompress/Readers/AbstractReader.cs +++ b/src/SharpCompress/Readers/AbstractReader.cs @@ -180,15 +180,13 @@ public void WriteEntryTo(Stream writableStream) "A writable Stream was required. Use Cancel if that was intended."); } - var streamListener = this as IReaderExtractionListener; - streamListener.FireEntryExtractionBegin(Entry); - Write(writableStream, streamListener); - streamListener.FireEntryExtractionEnd(Entry); + Write(writableStream); wroteCurrentEntry = true; } - internal void Write(Stream writeStream, IReaderExtractionListener streamListener) + internal void Write(Stream writeStream) { + var streamListener = this as IReaderExtractionListener; using (Stream s = OpenEntryStream()) { s.TransferTo(writeStream, Entry, streamListener); @@ -247,28 +245,13 @@ void IExtractionListener.FireFilePartExtractionBegin(string name, long size, lon }); } } - - void IReaderExtractionListener.FireEntryExtractionBegin(Entry entry) - { - if (EntryExtractionBegin != null) - { - EntryExtractionBegin(this, new ReaderExtractionEventArgs(entry)); - } - } - void IReaderExtractionListener.FireEntryExtractionProgress(Entry entry, long bytesTransferred, int iterations) { if (EntryExtractionProgress != null) { - EntryExtractionProgress(this, new ReaderExtractionEventArgs(entry, new ReaderProgress(entry, bytesTransferred, iterations))); - } - } - - void IReaderExtractionListener.FireEntryExtractionEnd(Entry entry) - { - if (EntryExtractionEnd != null) - { - EntryExtractionEnd(this, new ReaderExtractionEventArgs(entry)); + EntryExtractionProgress(this, + new ReaderExtractionEventArgs(entry, new ReaderProgress(entry, bytesTransferred, iterations)) + ); } } } diff --git a/src/SharpCompress/Readers/IReader.cs b/src/SharpCompress/Readers/IReader.cs index 1f8dbdab1..db11164de 100644 --- a/src/SharpCompress/Readers/IReader.cs +++ b/src/SharpCompress/Readers/IReader.cs @@ -6,8 +6,6 @@ namespace SharpCompress.Readers { public interface IReader : IDisposable { - event EventHandler> EntryExtractionBegin; - event EventHandler> EntryExtractionEnd; event EventHandler> EntryExtractionProgress; event EventHandler CompressedBytesRead; diff --git a/src/SharpCompress/Readers/IReaderExtractionListener.cs b/src/SharpCompress/Readers/IReaderExtractionListener.cs index e00d9801f..4a4adc4eb 100644 --- a/src/SharpCompress/Readers/IReaderExtractionListener.cs +++ b/src/SharpCompress/Readers/IReaderExtractionListener.cs @@ -4,9 +4,6 @@ namespace SharpCompress.Readers { internal interface IReaderExtractionListener : IExtractionListener { - // void EnsureEntriesLoaded(); - void FireEntryExtractionBegin(Entry entry); - void FireEntryExtractionEnd(Entry entry); void FireEntryExtractionProgress(Entry entry, long sizeTransferred, int iterations); } } \ No newline at end of file