Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new event handler to allow tracking of progress of extraction progress for individual entry #226

Merged
merged 6 commits into from
Apr 25, 2017
5 changes: 4 additions & 1 deletion src/SharpCompress/Common/ReaderExtractionEventArgs.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
using System;
using SharpCompress.Readers;

namespace SharpCompress.Common
{
public class ReaderExtractionEventArgs<T> : EventArgs
{
internal ReaderExtractionEventArgs(T entry)
internal ReaderExtractionEventArgs(T entry, ReaderProgress readerProgress = null)
{
Item = entry;
ReaderProgress = readerProgress;
}

public T Item { get; private set; }
public ReaderProgress ReaderProgress { get; private set; }
}
}
24 changes: 8 additions & 16 deletions src/SharpCompress/Readers/AbstractReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public abstract class AbstractReader<TEntry, TVolume> : IReader, IReaderExtracti

public event EventHandler<ReaderExtractionEventArgs<IEntry>> EntryExtractionBegin;
public event EventHandler<ReaderExtractionEventArgs<IEntry>> EntryExtractionEnd;
public event EventHandler<ReaderExtractionEventArgs<IEntry>> EntryExtractionProgress;

public event EventHandler<CompressedBytesReadEventArgs> CompressedBytesRead;
public event EventHandler<FilePartExtractionBeginEventArgs> FilePartExtractionBegin;
Expand Down Expand Up @@ -179,18 +180,16 @@ 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.FireEntryExtractionEnd(Entry);
wroteCurrentEntry = true;
}

internal void Write(Stream writeStream)
{
var streamListener = this as IReaderExtractionListener;
using (Stream s = OpenEntryStream())
{
s.TransferTo(writeStream);
s.TransferTo(writeStream, Entry, streamListener);
}
}

Expand Down Expand Up @@ -246,20 +245,13 @@ void IExtractionListener.FireFilePartExtractionBegin(string name, long size, lon
});
}
}

void IReaderExtractionListener.FireEntryExtractionBegin(Entry entry)
{
if (EntryExtractionBegin != null)
{
EntryExtractionBegin(this, new ReaderExtractionEventArgs<IEntry>(entry));
}
}

void IReaderExtractionListener.FireEntryExtractionEnd(Entry entry)
void IReaderExtractionListener.FireEntryExtractionProgress(Entry entry, long bytesTransferred, int iterations)
{
if (EntryExtractionEnd != null)
if (EntryExtractionProgress != null)
{
EntryExtractionEnd(this, new ReaderExtractionEventArgs<IEntry>(entry));
EntryExtractionProgress(this,
new ReaderExtractionEventArgs<IEntry>(entry, new ReaderProgress(entry, bytesTransferred, iterations))
);
}
}
}
Expand Down
3 changes: 1 addition & 2 deletions src/SharpCompress/Readers/IReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ namespace SharpCompress.Readers
{
public interface IReader : IDisposable
{
event EventHandler<ReaderExtractionEventArgs<IEntry>> EntryExtractionBegin;
event EventHandler<ReaderExtractionEventArgs<IEntry>> EntryExtractionEnd;
event EventHandler<ReaderExtractionEventArgs<IEntry>> EntryExtractionProgress;

event EventHandler<CompressedBytesReadEventArgs> CompressedBytesRead;
event EventHandler<FilePartExtractionBeginEventArgs> FilePartExtractionBegin;
Expand Down
4 changes: 1 addition & 3 deletions src/SharpCompress/Readers/IReaderExtractionListener.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +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);
}
}
24 changes: 24 additions & 0 deletions src/SharpCompress/Readers/ReaderProgress.cs
Original file line number Diff line number Diff line change
@@ -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;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the way this was done


public ReaderProgress(IEntry entry, long bytesTransferred, int iterations)
{
_entry = entry;
BytesTransferred = bytesTransferred;
Iterations = iterations;
}
}
}
31 changes: 29 additions & 2 deletions src/SharpCompress/Utility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using SharpCompress.Readers;

namespace SharpCompress
{
Expand Down Expand Up @@ -231,17 +232,43 @@ public static DateTime DosDateToDateTime(Int32 iTime)

public static long TransferTo(this Stream source, Stream destination)
{
byte[] array = new byte[81920];
byte[] array = GetTransferByteArray();
int count;
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);
}
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 (ReadTransferBlock(source, array, out count))
{
total += count;
destination.Write(array, 0, count);
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;
Expand Down