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 commit is contained in:
Anders Gardebring
2017-04-20 11:45:53 +02:00
parent 58b4fe4f28
commit 467fc2d03d
10 changed files with 42 additions and 29 deletions

View File

@@ -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<long, int> partTransferredAction = null)
{
if (archiveEntry.Archive.Type == ArchiveType.Rar && archiveEntry.Archive.IsSolid)
{
@@ -32,7 +33,7 @@ namespace SharpCompress.Archives
{
using (Stream s = new ListeningStream(streamListener, entryStream))
{
s.TransferTo(streamToWriteTo);
s.TransferTo(streamToWriteTo, partTransferredAction);
}
}
streamListener.FireEntryExtractionEnd(archiveEntry);

View File

@@ -167,7 +167,7 @@ namespace SharpCompress.Readers
}
}
public void WriteEntryTo(Stream writableStream)
public void WriteEntryTo(Stream writableStream, Action<long, int> partTransferredAction = null)
{
if (wroteCurrentEntry)
{
@@ -175,22 +175,21 @@ namespace SharpCompress.Readers
}
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<long, int> partTransferredAction = null)
{
using (Stream s = OpenEntryStream())
{
s.TransferTo(writeStream);
s.TransferTo(writeStream, partTransferredAction);
}
}

View File

@@ -20,7 +20,8 @@ namespace SharpCompress.Readers
/// Decompresses the current entry to the stream. This cannot be called twice for the current entry.
/// </summary>
/// <param name="writableStream"></param>
void WriteEntryTo(Stream writableStream);
/// <param name="partTransferredAction"></param>
void WriteEntryTo(Stream writableStream, Action<long, int> partTransferredAction = null);
bool Cancelled { get; }
void Cancel();

View File

@@ -1,4 +1,5 @@
#if !NO_FILE
using System;
using System.IO;
using SharpCompress.Common;
#endif
@@ -39,8 +40,12 @@ namespace SharpCompress.Readers
/// <summary>
/// Extract to specific directory, retaining filename
/// </summary>
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<long, int> partTransferredAction = null
)
{
string destinationFileName = string.Empty;
string file = Path.GetFileName(reader.Entry.Key);
@@ -66,7 +71,7 @@ namespace SharpCompress.Readers
if (!reader.Entry.IsDirectory)
{
reader.WriteEntryToFile(destinationFileName, options);
reader.WriteEntryToFile(destinationFileName, options, partTransferredAction);
}
else if (options.ExtractFullPath && !Directory.Exists(destinationFileName))
{
@@ -77,8 +82,12 @@ namespace SharpCompress.Readers
/// <summary>
/// Extract to specific file
/// </summary>
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<long, int> partTransferredAction = null
)
{
FileMode fm = FileMode.Create;
options = options ?? new ExtractionOptions()
@@ -92,7 +101,7 @@ namespace SharpCompress.Readers
}
using (FileStream fs = File.Open(destinationFileName, fm))
{
reader.WriteEntryTo(fs);
reader.WriteEntryTo(fs, partTransferredAction);
//using (Stream s = reader.OpenEntryStream())
//{
// s.TransferTo(fs);

View File

@@ -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<long, int> 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;
}

View File

@@ -24,7 +24,7 @@ namespace SharpCompress.Writers
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<long, int> partTransferredAction = null);
protected virtual void Dispose(bool isDisposing)
{

View File

@@ -26,7 +26,7 @@ namespace SharpCompress.Writers.GZip
base.Dispose(isDisposing);
}
public override void Write(string filename, Stream source, DateTime? modificationTime)
public override void Write(string filename, Stream source, DateTime? modificationTime, Action<long, int> partTransferredAction = null)
{
if (wroteToStream)
{
@@ -35,7 +35,7 @@ namespace SharpCompress.Writers.GZip
GZipStream stream = OutputStream as GZipStream;
stream.FileName = filename;
stream.LastModified = modificationTime;
source.TransferTo(stream);
source.TransferTo(stream, partTransferredAction);
wroteToStream = true;
}
}

View File

@@ -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<long, int> partTransferredAction = null);
}
}

View File

@@ -39,9 +39,9 @@ namespace SharpCompress.Writers.Tar
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<long, int> partTransferredAction = null)
{
Write(filename, source, modificationTime, null);
Write(filename, source, modificationTime, null, partTransferredAction);
}
private string NormalizeFilename(string filename)
@@ -57,7 +57,7 @@ namespace SharpCompress.Writers.Tar
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<long, int> partTransferredAction = null)
{
if (!source.CanSeek && size == null)
{
@@ -71,7 +71,7 @@ namespace SharpCompress.Writers.Tar
header.Name = NormalizeFilename(filename);
header.Size = realSize;
header.Write(OutputStream);
size = source.TransferTo(OutputStream);
size = source.TransferTo(OutputStream, partTransferredAction);
PadTo512(size.Value, false);
}

View File

@@ -90,19 +90,19 @@ namespace SharpCompress.Writers.Zip
}
}
public override void Write(string entryPath, Stream source, DateTime? modificationTime)
public override void Write(string entryPath, Stream source, DateTime? modificationTime, Action<long, int> 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<long, int> partTransferredAction = null)
{
using (Stream output = WriteToStream(entryPath, zipWriterEntryOptions))
{
source.TransferTo(output);
source.TransferTo(output, partTransferredAction);
}
}