Renamespace for proper pluralization

This commit is contained in:
Adam Hathcock
2016-09-26 11:49:49 +01:00
parent c24cdc66ed
commit d732e3cfa4
188 changed files with 335 additions and 339 deletions

View File

@@ -0,0 +1,266 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using SharpCompress.Common;
namespace SharpCompress.Readers
{
/// <summary>
/// A generic push reader that reads unseekable comrpessed streams.
/// </summary>
public abstract class AbstractReader<TEntry, TVolume> : IReader, IReaderExtractionListener
where TEntry : Entry
where TVolume : Volume
{
private bool completed;
private IEnumerator<TEntry> entriesForCurrentReadStream;
private bool wroteCurrentEntry;
public event EventHandler<ReaderExtractionEventArgs<IEntry>> EntryExtractionBegin;
public event EventHandler<ReaderExtractionEventArgs<IEntry>> EntryExtractionEnd;
public event EventHandler<CompressedBytesReadEventArgs> CompressedBytesRead;
public event EventHandler<FilePartExtractionBeginEventArgs> FilePartExtractionBegin;
internal AbstractReader(Options options, ArchiveType archiveType)
{
ArchiveType = archiveType;
Options = options;
}
internal Options Options { get; private set; }
public ArchiveType ArchiveType { get; }
/// <summary>
/// Current volume that the current entry resides in
/// </summary>
public abstract TVolume Volume { get; }
/// <summary>
/// Current file entry
/// </summary>
public TEntry Entry { get { return entriesForCurrentReadStream.Current; } }
#region IDisposable Members
public void Dispose()
{
if (entriesForCurrentReadStream != null)
{
entriesForCurrentReadStream.Dispose();
}
Volume.Dispose();
}
#endregion
public bool Cancelled { get; private set; }
/// <summary>
/// Indicates that the remaining entries are not required.
/// On dispose of an EntryStream, the stream will not skip to the end of the entry.
/// An attempt to move to the next entry will throw an exception, as the compressed stream is not positioned at an entry boundary.
/// </summary>
public void Cancel()
{
if (!completed)
{
Cancelled = true;
}
}
public bool MoveToNextEntry()
{
if (completed)
{
return false;
}
if (Cancelled)
{
throw new InvalidOperationException("Reader has been cancelled.");
}
if (entriesForCurrentReadStream == null)
{
return LoadStreamForReading(RequestInitialStream());
}
if (!wroteCurrentEntry)
{
SkipEntry();
}
wroteCurrentEntry = false;
if (NextEntryForCurrentStream())
{
return true;
}
completed = true;
return false;
}
internal bool LoadStreamForReading(Stream stream)
{
if (entriesForCurrentReadStream != null)
{
entriesForCurrentReadStream.Dispose();
}
if ((stream == null) || (!stream.CanRead))
{
throw new MultipartStreamRequiredException("File is split into multiple archives: '"
+ Entry.Key +
"'. A new readable stream is required. Use Cancel if it was intended.");
}
entriesForCurrentReadStream = GetEntries(stream).GetEnumerator();
if (entriesForCurrentReadStream.MoveNext())
{
return true;
}
return false;
}
internal virtual Stream RequestInitialStream()
{
return Volume.Stream;
}
internal virtual bool NextEntryForCurrentStream()
{
return entriesForCurrentReadStream.MoveNext();
}
internal abstract IEnumerable<TEntry> GetEntries(Stream stream);
#region Entry Skip/Write
private void SkipEntry()
{
if (!Entry.IsDirectory)
{
Skip();
}
}
private readonly byte[] skipBuffer = new byte[4096];
private void Skip()
{
if (!Entry.IsSolid)
{
var rawStream = Entry.Parts.First().GetRawStream();
if (rawStream != null)
{
var bytesToAdvance = Entry.CompressedSize;
for (var i = 0; i < bytesToAdvance / skipBuffer.Length; i++)
{
rawStream.Read(skipBuffer, 0, skipBuffer.Length);
}
rawStream.Read(skipBuffer, 0, (int)(bytesToAdvance % skipBuffer.Length));
return;
}
}
using (var s = OpenEntryStream())
{
while (s.Read(skipBuffer, 0, skipBuffer.Length) > 0)
{
}
}
}
public void WriteEntryTo(Stream writableStream)
{
if (wroteCurrentEntry)
{
throw new ArgumentException("WriteEntryTo or OpenEntryStream can only be called once.");
}
if ((writableStream == null) || (!writableStream.CanWrite))
{
throw new ArgumentNullException(
"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)
{
using (Stream s = OpenEntryStream())
{
s.TransferTo(writeStream);
}
}
public EntryStream OpenEntryStream()
{
if (wroteCurrentEntry)
{
throw new ArgumentException("WriteEntryTo or OpenEntryStream can only be called once.");
}
var stream = GetEntryStream();
wroteCurrentEntry = true;
return stream;
}
/// <summary>
/// Retains a reference to the entry stream, so we can check whether it completed later.
/// </summary>
protected EntryStream CreateEntryStream(Stream decompressed)
{
return new EntryStream(this, decompressed);
}
protected virtual EntryStream GetEntryStream()
{
return CreateEntryStream(Entry.Parts.First().GetCompressedStream());
}
#endregion
IEntry IReader.Entry { get { return Entry; } }
void IExtractionListener.FireCompressedBytesRead(long currentPartCompressedBytes, long compressedReadBytes)
{
if (CompressedBytesRead != null)
{
CompressedBytesRead(this, new CompressedBytesReadEventArgs
{
CurrentFilePartCompressedBytesRead = currentPartCompressedBytes,
CompressedBytesRead = compressedReadBytes
});
}
}
void IExtractionListener.FireFilePartExtractionBegin(string name, long size, long compressedSize)
{
if (FilePartExtractionBegin != null)
{
FilePartExtractionBegin(this, new FilePartExtractionBeginEventArgs
{
CompressedSize = compressedSize,
Size = size,
Name = name
});
}
}
void IReaderExtractionListener.FireEntryExtractionBegin(Entry entry)
{
if (EntryExtractionBegin != null)
{
EntryExtractionBegin(this, new ReaderExtractionEventArgs<IEntry>(entry));
}
}
void IReaderExtractionListener.FireEntryExtractionEnd(Entry entry)
{
if (EntryExtractionEnd != null)
{
EntryExtractionEnd(this, new ReaderExtractionEventArgs<IEntry>(entry));
}
}
}
}

View File

@@ -0,0 +1,40 @@
using System.Collections.Generic;
using System.IO;
using SharpCompress.Common;
using SharpCompress.Common.GZip;
namespace SharpCompress.Readers.GZip
{
public class GZipReader : AbstractReader<GZipEntry, GZipVolume>
{
internal GZipReader(Stream stream, Options options)
: base(options, ArchiveType.GZip)
{
Volume = new GZipVolume(stream, options);
}
public override GZipVolume Volume { get; }
#region Open
/// <summary>
/// Opens a GZipReader for Non-seeking usage with a single volume
/// </summary>
/// <param name="stream"></param>
/// <param name="options"></param>
/// <returns></returns>
public static GZipReader Open(Stream stream,
Options options = Options.KeepStreamsOpen)
{
stream.CheckNotNull("stream");
return new GZipReader(stream, options);
}
#endregion
internal override IEnumerable<GZipEntry> GetEntries(Stream stream)
{
return GZipEntry.GetEntries(stream);
}
}
}

View File

@@ -0,0 +1,40 @@
using System;
using System.IO;
using SharpCompress.Common;
namespace SharpCompress.Readers
{
public interface IReader : IDisposable
{
event EventHandler<ReaderExtractionEventArgs<IEntry>> EntryExtractionBegin;
event EventHandler<ReaderExtractionEventArgs<IEntry>> EntryExtractionEnd;
event EventHandler<CompressedBytesReadEventArgs> CompressedBytesRead;
event EventHandler<FilePartExtractionBeginEventArgs> FilePartExtractionBegin;
ArchiveType ArchiveType { get; }
IEntry Entry { get; }
/// <summary>
/// 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);
bool Cancelled { get; }
void Cancel();
/// <summary>
/// Moves to the next entry by reading more data from the underlying stream. This skips if data has not been read.
/// </summary>
/// <returns></returns>
bool MoveToNextEntry();
/// <summary>
/// Opens the current entry as a stream that will decompress as it is read.
/// Read the entire stream or use SkipEntry on EntryStream.
/// </summary>
EntryStream OpenEntryStream();
}
}

View File

@@ -0,0 +1,98 @@
#if !NO_FILE
using System.IO;
using SharpCompress.Common;
#endif
namespace SharpCompress.Readers
{
public static class IReaderExtensions
{
#if !NO_FILE
public static void WriteEntryTo(this IReader reader, string filePath)
{
using (Stream stream = File.Open(filePath, FileMode.Create, FileAccess.Write))
{
reader.WriteEntryTo(stream);
}
}
public static void WriteEntryTo(this IReader reader, FileInfo filePath)
{
using (Stream stream = filePath.Open(FileMode.Create))
{
reader.WriteEntryTo(stream);
}
}
/// <summary>
/// Extract all remaining unread entries to specific directory, retaining filename
/// </summary>
public static void WriteAllToDirectory(this IReader reader, string destinationDirectory,
ExtractOptions options = ExtractOptions.Overwrite)
{
while (reader.MoveToNextEntry())
{
reader.WriteEntryToDirectory(destinationDirectory, options);
}
}
/// <summary>
/// Extract to specific directory, retaining filename
/// </summary>
public static void WriteEntryToDirectory(this IReader reader, string destinationDirectory,
ExtractOptions options = ExtractOptions.Overwrite)
{
string destinationFileName = string.Empty;
string file = Path.GetFileName(reader.Entry.Key);
if (options.HasFlag(ExtractOptions.ExtractFullPath))
{
string folder = Path.GetDirectoryName(reader.Entry.Key);
string destdir = Path.Combine(destinationDirectory, folder);
if (!Directory.Exists(destdir))
{
Directory.CreateDirectory(destdir);
}
destinationFileName = Path.Combine(destdir, file);
}
else
{
destinationFileName = Path.Combine(destinationDirectory, file);
}
if (!reader.Entry.IsDirectory)
{
reader.WriteEntryToFile(destinationFileName, options);
}
else if (options.HasFlag(ExtractOptions.ExtractFullPath) && !Directory.Exists(destinationFileName))
{
Directory.CreateDirectory(destinationFileName);
}
}
/// <summary>
/// Extract to specific file
/// </summary>
public static void WriteEntryToFile(this IReader reader, string destinationFileName,
ExtractOptions options = ExtractOptions.Overwrite)
{
FileMode fm = FileMode.Create;
if (!options.HasFlag(ExtractOptions.Overwrite))
{
fm = FileMode.CreateNew;
}
using (FileStream fs = File.Open(destinationFileName, fm))
{
reader.WriteEntryTo(fs);
//using (Stream s = reader.OpenEntryStream())
//{
// s.TransferTo(fs);
//}
}
reader.Entry.PreserveExtractionOptions(destinationFileName, options);
}
#endif
}
}

View File

@@ -0,0 +1,11 @@
using SharpCompress.Common;
namespace SharpCompress.Readers
{
internal interface IReaderExtractionListener : IExtractionListener
{
// void EnsureEntriesLoaded();
void FireEntryExtractionBegin(Entry entry);
void FireEntryExtractionEnd(Entry entry);
}
}

View File

@@ -0,0 +1,124 @@
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using SharpCompress.Common;
using SharpCompress.Common.Rar;
namespace SharpCompress.Readers.Rar
{
internal class MultiVolumeRarReader : RarReader
{
private readonly IEnumerator<Stream> streams;
private Stream tempStream;
internal MultiVolumeRarReader(IEnumerable<Stream> streams, Options options)
: base(options)
{
this.streams = streams.GetEnumerator();
}
internal override void ValidateArchive(RarVolume archive)
{
}
internal override Stream RequestInitialStream()
{
if (streams.MoveNext())
{
return streams.Current;
}
throw new MultiVolumeExtractionException("No stream provided when requested by MultiVolumeRarReader");
}
internal override bool NextEntryForCurrentStream()
{
if (!base.NextEntryForCurrentStream())
{
//if we're got another stream to try to process then do so
if (streams.MoveNext() && LoadStreamForReading(streams.Current))
{
return true;
}
return false;
}
return true;
}
protected override IEnumerable<FilePart> CreateFilePartEnumerableForCurrentEntry()
{
var enumerator = new MultiVolumeStreamEnumerator(this, streams, tempStream);
tempStream = null;
return enumerator;
}
private class MultiVolumeStreamEnumerator : IEnumerable<FilePart>, IEnumerator<FilePart>
{
private readonly MultiVolumeRarReader reader;
private readonly IEnumerator<Stream> nextReadableStreams;
private Stream tempStream;
private bool isFirst = true;
internal MultiVolumeStreamEnumerator(MultiVolumeRarReader r, IEnumerator<Stream> nextReadableStreams,
Stream tempStream)
{
reader = r;
this.nextReadableStreams = nextReadableStreams;
this.tempStream = tempStream;
}
public IEnumerator<FilePart> GetEnumerator()
{
return this;
}
IEnumerator IEnumerable.GetEnumerator()
{
return this;
}
public FilePart Current { get; private set; }
public void Dispose()
{
}
object IEnumerator.Current { get { return Current; } }
public bool MoveNext()
{
if (isFirst)
{
Current = reader.Entry.Parts.First();
isFirst = false; //first stream already to go
return true;
}
if (!reader.Entry.IsSplit)
{
return false;
}
if (tempStream != null)
{
reader.LoadStreamForReading(tempStream);
tempStream = null;
}
else if (!nextReadableStreams.MoveNext())
{
throw new MultiVolumeExtractionException("No stream provided when requested by MultiVolumeRarReader");
}
else
{
reader.LoadStreamForReading(nextReadableStreams.Current);
}
Current = reader.Entry.Parts.First();
return true;
}
public void Reset()
{
}
}
}
}

View File

@@ -0,0 +1,21 @@
using System.IO;
using SharpCompress.Common.Rar;
using SharpCompress.Common.Rar.Headers;
namespace SharpCompress.Readers.Rar
{
internal class NonSeekableStreamFilePart : RarFilePart
{
internal NonSeekableStreamFilePart(MarkHeader mh, FileHeader fh)
: base(mh, fh)
{
}
internal override Stream GetCompressedStream()
{
return FileHeader.PackedStream;
}
internal override string FilePartName { get { return "Unknown Stream - File Entry: " + FileHeader.FileName; } }
}
}

View File

@@ -0,0 +1,83 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using SharpCompress.Common;
using SharpCompress.Common.Rar;
using SharpCompress.Compressors.Rar;
namespace SharpCompress.Readers.Rar
{
/// <summary>
/// This class faciliates Reading a Rar Archive in a non-seekable forward-only manner
/// </summary>
public abstract class RarReader : AbstractReader<RarReaderEntry, RarVolume>
{
public string Password { get; set; }
private RarVolume volume;
private readonly Unpack pack = new Unpack();
internal RarReader(Options options)
: base(options, ArchiveType.Rar)
{
}
internal abstract void ValidateArchive(RarVolume archive);
public override RarVolume Volume { get { return volume; } }
#region Open
/// <summary>
/// Opens a RarReader for Non-seeking usage with a single volume
/// </summary>
/// <param name="stream"></param>
/// <param name="options"></param>
/// <returns></returns>
public static RarReader Open(Stream stream, Options options = Options.KeepStreamsOpen)
{
return Open(stream, null, options);
}
/// <summary>
/// Opens a RarReader for Non-seeking usage with multiple volumes
/// </summary>
/// <param name="streams"></param>
/// <param name="options"></param>
/// <returns></returns>
public static RarReader Open(IEnumerable<Stream> streams, Options options = Options.KeepStreamsOpen)
{
streams.CheckNotNull("streams");
return new MultiVolumeRarReader(streams, options);
}
#endregion
internal override IEnumerable<RarReaderEntry> GetEntries(Stream stream)
{
volume = new RarReaderVolume(stream, Password, Options);
foreach (RarFilePart fp in volume.ReadFileParts())
{
ValidateArchive(volume);
yield return new RarReaderEntry(volume.IsSolidArchive, fp);
}
}
protected virtual IEnumerable<FilePart> CreateFilePartEnumerableForCurrentEntry()
{
return Entry.Parts;
}
protected override EntryStream GetEntryStream()
{
return CreateEntryStream(new RarStream(pack, Entry.FileHeader,
new MultiVolumeReadOnlyStream(
CreateFilePartEnumerableForCurrentEntry().Cast<RarFilePart>(), this)));
}
public static RarReader Open(Stream stream, string password, Options options = Options.KeepStreamsOpen)
{
stream.CheckNotNull("stream");
return new SingleVolumeRarReader(stream, password, options);
}
}
}

View File

@@ -0,0 +1,34 @@
using System.Collections.Generic;
using SharpCompress.Common;
using SharpCompress.Common.Rar;
using SharpCompress.Common.Rar.Headers;
namespace SharpCompress.Readers.Rar
{
public class RarReaderEntry : RarEntry
{
internal RarReaderEntry(bool solid, RarFilePart part)
{
Part = part;
IsSolid = solid;
}
internal RarFilePart Part { get; }
internal override IEnumerable<FilePart> Parts { get { return Part.AsEnumerable<FilePart>(); } }
internal override FileHeader FileHeader { get { return Part.FileHeader; } }
public override CompressionType CompressionType { get { return CompressionType.Rar; } }
/// <summary>
/// The compressed file size
/// </summary>
public override long CompressedSize { get { return Part.FileHeader.CompressedSize; } }
/// <summary>
/// The uncompressed file size
/// </summary>
public override long Size { get { return Part.FileHeader.UncompressedSize; } }
}
}

View File

@@ -0,0 +1,27 @@
using System.Collections.Generic;
using System.IO;
using SharpCompress.Common;
using SharpCompress.Common.Rar;
using SharpCompress.Common.Rar.Headers;
using SharpCompress.IO;
namespace SharpCompress.Readers.Rar
{
public class RarReaderVolume : RarVolume
{
internal RarReaderVolume(Stream stream, string password, Options options)
: base(StreamingMode.Streaming, stream, password, options)
{
}
internal override RarFilePart CreateFilePart(FileHeader fileHeader, MarkHeader markHeader)
{
return new NonSeekableStreamFilePart(markHeader, fileHeader);
}
internal override IEnumerable<RarFilePart> ReadFileParts()
{
return GetVolumeFileParts();
}
}
}

View File

@@ -0,0 +1,32 @@
using System.IO;
using SharpCompress.Common;
using SharpCompress.Common.Rar;
namespace SharpCompress.Readers.Rar
{
internal class SingleVolumeRarReader : RarReader
{
private readonly Stream stream;
internal SingleVolumeRarReader(Stream stream, string password, Options options)
: base(options)
{
Password = password;
this.stream = stream;
}
internal override void ValidateArchive(RarVolume archive)
{
if (archive.IsMultiVolume)
{
throw new MultiVolumeExtractionException(
"Streamed archive is a Multi-volume archive. Use different RarReader method to extract.");
}
}
internal override Stream RequestInitialStream()
{
return stream;
}
}
}

View File

@@ -0,0 +1,80 @@
using System;
using System.IO;
using SharpCompress.Archives.GZip;
using SharpCompress.Archives.Rar;
using SharpCompress.Archives.Tar;
using SharpCompress.Archives.Zip;
using SharpCompress.Common;
using SharpCompress.Compressors;
using SharpCompress.Compressors.BZip2;
using SharpCompress.Compressors.Deflate;
using SharpCompress.IO;
using SharpCompress.Readers.GZip;
using SharpCompress.Readers.Rar;
using SharpCompress.Readers.Tar;
using SharpCompress.Readers.Zip;
namespace SharpCompress.Readers
{
public static class ReaderFactory
{
/// <summary>
/// Opens a Reader for Non-seeking usage
/// </summary>
/// <param name="stream"></param>
/// <param name="options"></param>
/// <returns></returns>
public static IReader Open(Stream stream, Options options = Options.KeepStreamsOpen)
{
stream.CheckNotNull("stream");
RewindableStream rewindableStream = new RewindableStream(stream);
rewindableStream.StartRecording();
if (ZipArchive.IsZipFile(rewindableStream, null))
{
rewindableStream.Rewind(true);
return ZipReader.Open(rewindableStream, null, options);
}
rewindableStream.Rewind(false);
if (GZipArchive.IsGZipFile(rewindableStream))
{
rewindableStream.Rewind(false);
GZipStream testStream = new GZipStream(rewindableStream, CompressionMode.Decompress);
if (TarArchive.IsTarFile(testStream))
{
rewindableStream.Rewind(true);
return new TarReader(rewindableStream, CompressionType.GZip, options);
}
rewindableStream.Rewind(true);
return GZipReader.Open(rewindableStream, options);
}
rewindableStream.Rewind(false);
if (BZip2Stream.IsBZip2(rewindableStream))
{
rewindableStream.Rewind(false);
BZip2Stream testStream = new BZip2Stream(rewindableStream, CompressionMode.Decompress, true);
if (TarArchive.IsTarFile(testStream))
{
rewindableStream.Rewind(true);
return new TarReader(rewindableStream, CompressionType.BZip2, options);
}
}
rewindableStream.Rewind(false);
if (RarArchive.IsRarFile(rewindableStream, options))
{
rewindableStream.Rewind(true);
return RarReader.Open(rewindableStream, options);
}
rewindableStream.Rewind(false);
if (TarArchive.IsTarFile(rewindableStream))
{
rewindableStream.Rewind(true);
return TarReader.Open(rewindableStream, options);
}
throw new InvalidOperationException("Cannot determine compressed stream type. Supported Reader Formats: Zip, GZip, BZip2, Tar, Rar");
}
}
}

View File

@@ -0,0 +1,102 @@
using System;
using System.Collections.Generic;
using System.IO;
using SharpCompress.Archives.GZip;
using SharpCompress.Archives.Tar;
using SharpCompress.Common;
using SharpCompress.Common.Tar;
using SharpCompress.Compressors;
using SharpCompress.Compressors.BZip2;
using SharpCompress.Compressors.Deflate;
using SharpCompress.IO;
namespace SharpCompress.Readers.Tar
{
public class TarReader : AbstractReader<TarEntry, TarVolume>
{
private readonly CompressionType compressionType;
internal TarReader(Stream stream, CompressionType compressionType,
Options options)
: base(options, ArchiveType.Tar)
{
this.compressionType = compressionType;
Volume = new TarVolume(stream, options);
}
public override TarVolume Volume { get; }
internal override Stream RequestInitialStream()
{
var stream = base.RequestInitialStream();
switch (compressionType)
{
case CompressionType.BZip2:
{
return new BZip2Stream(stream, CompressionMode.Decompress, false);
}
case CompressionType.GZip:
{
return new GZipStream(stream, CompressionMode.Decompress);
}
case CompressionType.None:
{
return stream;
}
default:
{
throw new NotSupportedException("Invalid compression type: " + compressionType);
}
}
}
#region Open
/// <summary>
/// Opens a TarReader for Non-seeking usage with a single volume
/// </summary>
/// <param name="stream"></param>
/// <param name="options"></param>
/// <returns></returns>
public static TarReader Open(Stream stream, Options options = Options.KeepStreamsOpen)
{
stream.CheckNotNull("stream");
RewindableStream rewindableStream = new RewindableStream(stream);
rewindableStream.StartRecording();
if (GZipArchive.IsGZipFile(rewindableStream))
{
rewindableStream.Rewind(false);
GZipStream testStream = new GZipStream(rewindableStream, CompressionMode.Decompress);
if (TarArchive.IsTarFile(testStream))
{
rewindableStream.Rewind(true);
return new TarReader(rewindableStream, CompressionType.GZip, options);
}
throw new InvalidFormatException("Not a tar file.");
}
rewindableStream.Rewind(false);
if (BZip2Stream.IsBZip2(rewindableStream))
{
rewindableStream.Rewind(false);
BZip2Stream testStream = new BZip2Stream(rewindableStream, CompressionMode.Decompress, false);
if (TarArchive.IsTarFile(testStream))
{
rewindableStream.Rewind(true);
return new TarReader(rewindableStream, CompressionType.BZip2, options);
}
throw new InvalidFormatException("Not a tar file.");
}
rewindableStream.Rewind(true);
return new TarReader(rewindableStream, CompressionType.None, options);
}
#endregion
internal override IEnumerable<TarEntry> GetEntries(Stream stream)
{
return TarEntry.GetEntries(StreamingMode.Streaming, stream, compressionType);
}
}
}

View File

@@ -0,0 +1,63 @@
using System.Collections.Generic;
using System.IO;
using SharpCompress.Common;
using SharpCompress.Common.Zip;
using SharpCompress.Common.Zip.Headers;
namespace SharpCompress.Readers.Zip
{
public class ZipReader : AbstractReader<ZipEntry, ZipVolume>
{
private readonly StreamingZipHeaderFactory headerFactory;
internal ZipReader(Stream stream, Options options, string password)
: base(options, ArchiveType.Zip)
{
Volume = new ZipVolume(stream, options);
headerFactory = new StreamingZipHeaderFactory(password);
}
public override ZipVolume Volume { get; }
#region Open
/// <summary>
/// Opens a ZipReader for Non-seeking usage with a single volume
/// </summary>
/// <param name="stream"></param>
/// <param name="options"></param>
/// <param name="password"></param>
/// <returns></returns>
public static ZipReader Open(Stream stream, string password = null,
Options options = Options.KeepStreamsOpen)
{
stream.CheckNotNull("stream");
return new ZipReader(stream, options, password);
}
#endregion
internal override IEnumerable<ZipEntry> GetEntries(Stream stream)
{
foreach (ZipHeader h in headerFactory.ReadStreamHeader(stream))
{
if (h != null)
{
switch (h.ZipHeaderType)
{
case ZipHeaderType.LocalEntry:
{
yield return new ZipEntry(new StreamingZipFilePart(h as LocalEntryHeader,
stream));
}
break;
case ZipHeaderType.DirectoryEnd:
{
yield break;
}
}
}
}
}
}
}