mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-07-10 11:07:22 +00:00
Moved ExtractTo to common logic
This commit is contained in:
@@ -7,7 +7,7 @@ using SharpCompress.Reader;
|
||||
|
||||
namespace SharpCompress.Archive
|
||||
{
|
||||
public abstract class AbstractArchive<TEntry, TVolume> : IArchive, IStreamListener
|
||||
public abstract class AbstractArchive<TEntry, TVolume> : IArchive, IArchiveExtractionListener
|
||||
where TEntry : IArchiveEntry
|
||||
where TVolume : IVolume
|
||||
{
|
||||
@@ -23,7 +23,7 @@ namespace SharpCompress.Archive
|
||||
#if !PORTABLE && !NETFX_CORE
|
||||
internal AbstractArchive(ArchiveType type, FileInfo fileInfo, Options options)
|
||||
{
|
||||
this.Type = type;
|
||||
Type = type;
|
||||
if (!fileInfo.Exists)
|
||||
{
|
||||
throw new ArgumentException("File does not exist: " + fileInfo.FullName);
|
||||
@@ -52,7 +52,7 @@ namespace SharpCompress.Archive
|
||||
lazyEntries = new LazyReadOnlyCollection<TEntry>(Enumerable.Empty<TEntry>());
|
||||
}
|
||||
|
||||
internal void FireEntryExtractionBegin(IArchiveEntry entry)
|
||||
void IArchiveExtractionListener.FireEntryExtractionBegin(IArchiveEntry entry)
|
||||
{
|
||||
if (EntryExtractionBegin != null)
|
||||
{
|
||||
@@ -60,7 +60,7 @@ namespace SharpCompress.Archive
|
||||
}
|
||||
}
|
||||
|
||||
internal void FireEntryExtractionEnd(IArchiveEntry entry)
|
||||
void IArchiveExtractionListener.FireEntryExtractionEnd(IArchiveEntry entry)
|
||||
{
|
||||
if (EntryExtractionEnd != null)
|
||||
{
|
||||
@@ -128,7 +128,7 @@ namespace SharpCompress.Archive
|
||||
}
|
||||
}
|
||||
|
||||
internal void EnsureEntriesLoaded()
|
||||
void IArchiveExtractionListener.EnsureEntriesLoaded()
|
||||
{
|
||||
lazyEntries.EnsureFullyLoaded();
|
||||
lazyVolumes.EnsureFullyLoaded();
|
||||
@@ -137,7 +137,7 @@ namespace SharpCompress.Archive
|
||||
|
||||
public ArchiveType Type { get; private set; }
|
||||
|
||||
void IStreamListener.FireCompressedBytesRead(long currentPartCompressedBytes, long compressedReadBytes)
|
||||
void IExtractionListener.FireCompressedBytesRead(long currentPartCompressedBytes, long compressedReadBytes)
|
||||
{
|
||||
if (CompressedBytesRead != null)
|
||||
{
|
||||
@@ -149,7 +149,7 @@ namespace SharpCompress.Archive
|
||||
}
|
||||
}
|
||||
|
||||
void IStreamListener.FireFilePartExtractionBegin(string name, long size, long compressedSize)
|
||||
void IExtractionListener.FireFilePartExtractionBegin(string name, long size, long compressedSize)
|
||||
{
|
||||
if (FilePartExtractionBegin != null)
|
||||
{
|
||||
@@ -175,7 +175,7 @@ namespace SharpCompress.Archive
|
||||
/// <returns></returns>
|
||||
public IReader ExtractAllEntries()
|
||||
{
|
||||
EnsureEntriesLoaded();
|
||||
((IArchiveExtractionListener)this).EnsureEntriesLoaded();
|
||||
return CreateReaderForSolidExtraction();
|
||||
}
|
||||
|
||||
@@ -197,7 +197,7 @@ namespace SharpCompress.Archive
|
||||
{
|
||||
get
|
||||
{
|
||||
EnsureEntriesLoaded();
|
||||
((IArchiveExtractionListener)this).EnsureEntriesLoaded();
|
||||
return Entries.All(x => x.IsComplete);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Common.GZip;
|
||||
|
||||
namespace SharpCompress.Archive.GZip
|
||||
{
|
||||
public class GZipArchiveEntry : GZipEntry, IArchiveEntry
|
||||
{
|
||||
private readonly GZipArchive archive;
|
||||
|
||||
internal GZipArchiveEntry(GZipArchive archive, GZipFilePart part)
|
||||
: base(part)
|
||||
{
|
||||
this.archive = archive;
|
||||
Archive = archive;
|
||||
}
|
||||
|
||||
public virtual Stream OpenEntryStream()
|
||||
@@ -21,15 +19,7 @@ namespace SharpCompress.Archive.GZip
|
||||
}
|
||||
|
||||
#region IArchiveEntry Members
|
||||
|
||||
public void WriteTo(Stream streamToWriteTo)
|
||||
{
|
||||
if (IsEncrypted)
|
||||
{
|
||||
throw new PasswordProtectedException("Entry is password protected and cannot be extracted.");
|
||||
}
|
||||
this.Extract(archive, streamToWriteTo);
|
||||
}
|
||||
public IArchive Archive { get; private set; }
|
||||
|
||||
public bool IsComplete
|
||||
{
|
||||
|
||||
@@ -1,10 +1,39 @@
|
||||
using System.IO;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.IO;
|
||||
|
||||
namespace SharpCompress.Archive
|
||||
{
|
||||
public static class IArchiveEntryExtensions
|
||||
{
|
||||
public static void WriteTo(this IArchiveEntry archiveEntry, Stream streamToWriteTo)
|
||||
{
|
||||
if (archiveEntry.Archive.IsSolid)
|
||||
{
|
||||
throw new InvalidFormatException("Cannot use Archive random access on SOLID Rar files.");
|
||||
}
|
||||
|
||||
if (archiveEntry.IsEncrypted)
|
||||
{
|
||||
throw new PasswordProtectedException("Entry is password protected and cannot be extracted.");
|
||||
}
|
||||
|
||||
if (archiveEntry.IsDirectory)
|
||||
{
|
||||
throw new ExtractionException("Entry is a file directory and cannot be extracted.");
|
||||
}
|
||||
|
||||
var streamListener = archiveEntry.Archive as IArchiveExtractionListener;
|
||||
streamListener.EnsureEntriesLoaded();
|
||||
streamListener.FireEntryExtractionBegin(archiveEntry);
|
||||
streamListener.FireFilePartExtractionBegin(archiveEntry.FilePath, archiveEntry.Size, archiveEntry.CompressedSize);
|
||||
using (Stream s = new ListeningStream(streamListener, archiveEntry.OpenEntryStream()))
|
||||
{
|
||||
s.TransferTo(streamToWriteTo);
|
||||
}
|
||||
streamListener.FireEntryExtractionEnd(archiveEntry);
|
||||
}
|
||||
|
||||
#if !PORTABLE && !NETFX_CORE
|
||||
/// <summary>
|
||||
/// Extract to specific directory, retaining filename
|
||||
@@ -12,7 +41,7 @@ namespace SharpCompress.Archive
|
||||
public static void WriteToDirectory(this IArchiveEntry entry, string destinationDirectory,
|
||||
ExtractOptions options = ExtractOptions.Overwrite)
|
||||
{
|
||||
string destinationFileName = string.Empty;
|
||||
string destinationFileName;
|
||||
string file = Path.GetFileName(entry.FilePath);
|
||||
|
||||
|
||||
@@ -50,9 +79,7 @@ namespace SharpCompress.Archive
|
||||
fm = FileMode.CreateNew;
|
||||
}
|
||||
using (FileStream fs = File.Open(destinationFileName, fm))
|
||||
// using (Stream entryStream = entry.OpenEntryStream())
|
||||
{
|
||||
//entryStream.TransferTo(fs);
|
||||
entry.WriteTo(fs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,11 +11,11 @@ namespace SharpCompress.Archive
|
||||
/// </summary>
|
||||
Stream OpenEntryStream();
|
||||
|
||||
void WriteTo(Stream stream);
|
||||
|
||||
/// <summary>
|
||||
/// The archive can find all the parts of the archive needed to extract this entry.
|
||||
/// </summary>
|
||||
bool IsComplete { get; }
|
||||
|
||||
IArchive Archive { get; }
|
||||
}
|
||||
}
|
||||
11
SharpCompress/Archive/IArchiveExtractionListener.cs
Normal file
11
SharpCompress/Archive/IArchiveExtractionListener.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using SharpCompress.Common;
|
||||
|
||||
namespace SharpCompress.Archive
|
||||
{
|
||||
internal interface IArchiveExtractionListener : IExtractionListener
|
||||
{
|
||||
void EnsureEntriesLoaded();
|
||||
void FireEntryExtractionBegin(IArchiveEntry entry);
|
||||
void FireEntryExtractionEnd(IArchiveEntry entry);
|
||||
}
|
||||
}
|
||||
@@ -19,13 +19,5 @@ namespace SharpCompress.Archive.Rar
|
||||
{
|
||||
return archive.Volumes.First().IsMultiVolume;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// RarArchive is SOLID (this means the Archive saved bytes by reusing information which helps for archives containing many small files).
|
||||
/// </summary>
|
||||
public static bool IsSolidArchive(this RarArchive archive)
|
||||
{
|
||||
return archive.IsSolid;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,11 +11,12 @@ namespace SharpCompress.Archive.Rar
|
||||
public class RarArchiveEntry : RarEntry, IArchiveEntry
|
||||
{
|
||||
private readonly ICollection<RarFilePart> parts;
|
||||
private readonly RarArchive archive;
|
||||
|
||||
internal RarArchiveEntry(RarArchive archive, IEnumerable<RarFilePart> parts)
|
||||
{
|
||||
this.parts = parts.ToList();
|
||||
Archive = archive;
|
||||
this.archive = archive;
|
||||
}
|
||||
|
||||
public override CompressionType CompressionType
|
||||
@@ -23,11 +24,17 @@ namespace SharpCompress.Archive.Rar
|
||||
get { return CompressionType.Rar; }
|
||||
}
|
||||
|
||||
private RarArchive Archive { get; set; }
|
||||
public IArchive Archive
|
||||
{
|
||||
get
|
||||
{
|
||||
return archive;
|
||||
}
|
||||
}
|
||||
|
||||
internal override IEnumerable<FilePart> Parts
|
||||
{
|
||||
get { return parts.Cast<FilePart>(); }
|
||||
get { return parts; }
|
||||
}
|
||||
|
||||
internal override FileHeader FileHeader
|
||||
@@ -41,8 +48,7 @@ namespace SharpCompress.Archive.Rar
|
||||
{
|
||||
CheckIncomplete();
|
||||
return parts.Select(fp => fp.FileHeader)
|
||||
.Where(fh => !fh.FileFlags.HasFlag(FileFlags.SPLIT_AFTER))
|
||||
.Single().FileCRC;
|
||||
.Single(fh => !fh.FileFlags.HasFlag(FileFlags.SPLIT_AFTER)).FileCRC;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,22 +73,8 @@ namespace SharpCompress.Archive.Rar
|
||||
|
||||
public Stream OpenEntryStream()
|
||||
{
|
||||
return new RarStream(Archive.Unpack, FileHeader,
|
||||
new MultiVolumeReadOnlyStream(Parts.Cast<RarFilePart>(), Archive));
|
||||
}
|
||||
|
||||
public void WriteTo(Stream streamToWriteTo)
|
||||
{
|
||||
CheckIncomplete();
|
||||
if (Archive.IsSolidArchive())
|
||||
{
|
||||
throw new InvalidFormatException("Cannot use Archive random access on SOLID Rar files.");
|
||||
}
|
||||
if (IsEncrypted)
|
||||
{
|
||||
throw new PasswordProtectedException("Entry is password protected and cannot be extracted.");
|
||||
}
|
||||
this.Extract(Archive, streamToWriteTo);
|
||||
return new RarStream(archive.Unpack, FileHeader,
|
||||
new MultiVolumeReadOnlyStream(Parts.Cast<RarFilePart>(), archive));
|
||||
}
|
||||
|
||||
public bool IsComplete
|
||||
|
||||
@@ -1,32 +1,21 @@
|
||||
using System.IO;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Common.SevenZip;
|
||||
|
||||
namespace SharpCompress.Archive.SevenZip
|
||||
{
|
||||
public class SevenZipArchiveEntry : SevenZipEntry, IArchiveEntry
|
||||
{
|
||||
private SevenZipArchive archive;
|
||||
|
||||
internal SevenZipArchiveEntry(SevenZipArchive archive, SevenZipFilePart part)
|
||||
: base(part)
|
||||
{
|
||||
this.archive = archive;
|
||||
Archive = archive;
|
||||
}
|
||||
|
||||
public Stream OpenEntryStream()
|
||||
{
|
||||
return FilePart.GetCompressedStream();
|
||||
}
|
||||
|
||||
public void WriteTo(Stream stream)
|
||||
{
|
||||
if (IsEncrypted)
|
||||
{
|
||||
throw new PasswordProtectedException("Entry is password protected and cannot be extracted.");
|
||||
}
|
||||
this.Extract(archive, stream);
|
||||
}
|
||||
public IArchive Archive { get; private set; }
|
||||
|
||||
public bool IsComplete
|
||||
{
|
||||
|
||||
@@ -7,12 +7,10 @@ namespace SharpCompress.Archive.Tar
|
||||
{
|
||||
public class TarArchiveEntry : TarEntry, IArchiveEntry
|
||||
{
|
||||
private readonly TarArchive archive;
|
||||
|
||||
internal TarArchiveEntry(TarArchive archive, TarFilePart part, CompressionType compressionType)
|
||||
: base(part, compressionType)
|
||||
{
|
||||
this.archive = archive;
|
||||
Archive = archive;
|
||||
}
|
||||
|
||||
public virtual Stream OpenEntryStream()
|
||||
@@ -21,15 +19,7 @@ namespace SharpCompress.Archive.Tar
|
||||
}
|
||||
|
||||
#region IArchiveEntry Members
|
||||
|
||||
public void WriteTo(Stream streamToWriteTo)
|
||||
{
|
||||
if (IsEncrypted)
|
||||
{
|
||||
throw new PasswordProtectedException("Entry is password protected and cannot be extracted.");
|
||||
}
|
||||
this.Extract(archive, streamToWriteTo);
|
||||
}
|
||||
public IArchive Archive { get; private set; }
|
||||
|
||||
public bool IsComplete
|
||||
{
|
||||
|
||||
@@ -6,12 +6,10 @@ namespace SharpCompress.Archive.Zip
|
||||
{
|
||||
public class ZipArchiveEntry : ZipEntry, IArchiveEntry
|
||||
{
|
||||
private readonly ZipArchive archive;
|
||||
|
||||
internal ZipArchiveEntry(ZipArchive archive, SeekableZipFilePart part)
|
||||
: base(part)
|
||||
{
|
||||
this.archive = archive;
|
||||
Archive = archive;
|
||||
}
|
||||
|
||||
public virtual Stream OpenEntryStream()
|
||||
@@ -21,10 +19,7 @@ namespace SharpCompress.Archive.Zip
|
||||
|
||||
#region IArchiveEntry Members
|
||||
|
||||
public void WriteTo(Stream streamToWriteTo)
|
||||
{
|
||||
this.Extract(archive, streamToWriteTo);
|
||||
}
|
||||
public IArchive Archive { get; private set; }
|
||||
|
||||
public bool IsComplete
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace SharpCompress.Common
|
||||
{
|
||||
internal interface IStreamListener
|
||||
internal interface IExtractionListener
|
||||
{
|
||||
void FireFilePartExtractionBegin(string name, long size, long compressedSize);
|
||||
void FireCompressedBytesRead(long currentPartCompressedBytes, long compressedReadBytes);
|
||||
@@ -15,12 +15,12 @@ namespace SharpCompress.Compressor.Rar
|
||||
private IEnumerator<RarFilePart> filePartEnumerator;
|
||||
private Stream currentStream;
|
||||
|
||||
private readonly IStreamListener streamListener;
|
||||
private readonly IExtractionListener streamListener;
|
||||
|
||||
private long currentPartTotalReadBytes;
|
||||
private long currentEntryTotalReadBytes;
|
||||
|
||||
internal MultiVolumeReadOnlyStream(IEnumerable<RarFilePart> parts, IStreamListener streamListener)
|
||||
internal MultiVolumeReadOnlyStream(IEnumerable<RarFilePart> parts, IExtractionListener streamListener)
|
||||
{
|
||||
this.streamListener = streamListener;
|
||||
|
||||
|
||||
@@ -6,9 +6,9 @@ namespace SharpCompress.IO
|
||||
internal class ListeningStream : Stream
|
||||
{
|
||||
private long currentEntryTotalReadBytes;
|
||||
private IStreamListener listener;
|
||||
private IExtractionListener listener;
|
||||
|
||||
public ListeningStream(IStreamListener listener, Stream stream)
|
||||
public ListeningStream(IExtractionListener listener, Stream stream)
|
||||
{
|
||||
Stream = stream;
|
||||
this.listener = listener;
|
||||
|
||||
@@ -4,7 +4,6 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using SharpCompress.Common;
|
||||
|
||||
|
||||
#if PORTABLE
|
||||
using SharpCompress.Common.Rar.Headers;
|
||||
#endif
|
||||
@@ -14,7 +13,7 @@ namespace SharpCompress.Reader
|
||||
/// <summary>
|
||||
/// A generic push reader that reads unseekable comrpessed streams.
|
||||
/// </summary>
|
||||
public abstract class AbstractReader<TEntry, TVolume> : IReader, IStreamListener
|
||||
public abstract class AbstractReader<TEntry, TVolume> : IReader, IExtractionListener
|
||||
where TEntry : Entry
|
||||
where TVolume : Volume
|
||||
{
|
||||
@@ -199,7 +198,7 @@ namespace SharpCompress.Reader
|
||||
get { return Entry; }
|
||||
}
|
||||
|
||||
void IStreamListener.FireCompressedBytesRead(long currentPartCompressedBytes, long compressedReadBytes)
|
||||
void IExtractionListener.FireCompressedBytesRead(long currentPartCompressedBytes, long compressedReadBytes)
|
||||
{
|
||||
if (CompressedBytesRead != null)
|
||||
{
|
||||
@@ -211,7 +210,7 @@ namespace SharpCompress.Reader
|
||||
}
|
||||
}
|
||||
|
||||
void IStreamListener.FireFilePartExtractionBegin(string name, long size, long compressedSize)
|
||||
void IExtractionListener.FireFilePartExtractionBegin(string name, long size, long compressedSize)
|
||||
{
|
||||
if (FilePartExtractionBegin != null)
|
||||
{
|
||||
|
||||
@@ -117,6 +117,7 @@
|
||||
<Compile Include="Common\CompressionType.cs" />
|
||||
<Compile Include="Common\FilePartExtractionBeginEventArgs.cs" />
|
||||
<Compile Include="Common\GenericVolume.cs" />
|
||||
<Compile Include="Archive\IArchiveExtractionListener.cs" />
|
||||
<Compile Include="Common\IncompleteArchiveException.cs" />
|
||||
<Compile Include="Common\MultiVolumeExtractionException.cs" />
|
||||
<Compile Include="Common\PasswordProtectedException.cs" />
|
||||
@@ -266,7 +267,7 @@
|
||||
<Compile Include="Common\InvalidFormatException.cs" />
|
||||
<Compile Include="IO\ReadOnlySubStream.cs" />
|
||||
<Compile Include="IO\StreamingMode.cs" />
|
||||
<Compile Include="Common\IStreamListener.cs" />
|
||||
<Compile Include="Common\IExtractionListener.cs" />
|
||||
<Compile Include="Common\MultipartStreamRequiredException.cs" />
|
||||
<Compile Include="LazyReadOnlyCollection.cs" />
|
||||
<Compile Include="Archive\Rar\RarArchive.Extensions.cs" />
|
||||
|
||||
@@ -454,27 +454,6 @@ namespace SharpCompress
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
internal static void Extract<TEntry, TVolume>(this TEntry entry,
|
||||
AbstractArchive<TEntry, TVolume> archive, Stream streamToWriteTo)
|
||||
where TEntry : IArchiveEntry
|
||||
where TVolume : IVolume
|
||||
{
|
||||
if (entry.IsDirectory)
|
||||
{
|
||||
throw new ExtractionException("Entry is a file directory and cannot be extracted.");
|
||||
}
|
||||
|
||||
archive.EnsureEntriesLoaded();
|
||||
archive.FireEntryExtractionBegin(entry);
|
||||
((IStreamListener)archive).FireFilePartExtractionBegin(entry.FilePath, entry.Size, entry.CompressedSize);
|
||||
using (Stream s = new ListeningStream(archive, entry.OpenEntryStream()))
|
||||
{
|
||||
s.TransferTo(streamToWriteTo);
|
||||
}
|
||||
archive.FireEntryExtractionEnd(entry);
|
||||
}
|
||||
|
||||
#if PORTABLE || NETFX_CORE
|
||||
public static void CopyTo(this byte[] array, byte[] destination, int index)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user