From 683d2714d0b058b570ba4cbcda3e97c2cd4968e4 Mon Sep 17 00:00:00 2001 From: Anders Gardebring Date: Mon, 24 Apr 2017 13:50:45 +0200 Subject: [PATCH] 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 b33b8635..fd11e894 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 380e8df5..85289cb4 100644 --- a/src/SharpCompress/Readers/AbstractReader.cs +++ b/src/SharpCompress/Readers/AbstractReader.cs @@ -19,6 +19,7 @@ namespace SharpCompress.Readers public event EventHandler> EntryExtractionBegin; public event EventHandler> EntryExtractionEnd; + public event EventHandler> EntryExtractionProgress; public event EventHandler CompressedBytesRead; public event EventHandler FilePartExtractionBegin; @@ -181,16 +182,16 @@ namespace SharpCompress.Readers 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 @@ namespace SharpCompress.Readers } } + 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 0df03177..1f8dbdab 100644 --- a/src/SharpCompress/Readers/IReader.cs +++ b/src/SharpCompress/Readers/IReader.cs @@ -8,6 +8,7 @@ namespace SharpCompress.Readers { 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 226b0944..e00d9801 100644 --- a/src/SharpCompress/Readers/IReaderExtractionListener.cs +++ b/src/SharpCompress/Readers/IReaderExtractionListener.cs @@ -7,5 +7,6 @@ namespace SharpCompress.Readers // 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 00000000..94feb74d --- /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 451075f3..00952846 100644 --- a/src/SharpCompress/Utility.cs +++ b/src/SharpCompress/Utility.cs @@ -229,15 +229,18 @@ namespace SharpCompress 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; }