generalized multipart archive interface

This commit is contained in:
Vicente Penades
2022-12-03 13:44:19 +01:00
parent 8775b65f58
commit ca3d088785
10 changed files with 122 additions and 51 deletions

View File

@@ -8,6 +8,7 @@ using SharpCompress.Archives.SevenZip;
using SharpCompress.Archives.Tar;
using SharpCompress.Archives.Zip;
using SharpCompress.Common;
using SharpCompress.Factories;
using SharpCompress.IO;
using SharpCompress.Readers;
@@ -23,15 +24,9 @@ namespace SharpCompress.Archives
/// <returns></returns>
public static IArchive Open(Stream stream, ReaderOptions? readerOptions = null)
{
stream.CheckNotNull(nameof(stream));
if (!stream.CanRead || !stream.CanSeek)
{
throw new ArgumentException("Stream should be readable and seekable");
}
readerOptions ??= new ReaderOptions();
return FindArchiveFactory(stream).Open(stream, readerOptions);
return FindFactory<IArchiveFactory>(stream).Open(stream, readerOptions);
}
public static IWritableArchive Create(ArchiveType type)
@@ -62,11 +57,10 @@ namespace SharpCompress.Archives
/// <param name="fileInfo"></param>
/// <param name="options"></param>
public static IArchive Open(FileInfo fileInfo, ReaderOptions? options = null)
{
fileInfo.CheckNotNull(nameof(fileInfo));
{
options ??= new ReaderOptions { LeaveStreamOpen = false };
return FindArchiveFactory(fileInfo).Open(fileInfo, options);
return FindFactory<IArchiveFactory>(fileInfo).Open(fileInfo, options);
}
/// <summary>
@@ -87,7 +81,7 @@ namespace SharpCompress.Archives
fileInfo.CheckNotNull(nameof(fileInfo));
options ??= new ReaderOptions { LeaveStreamOpen = false };
return FindArchiveFactory(fileInfo).Open(fileInfos, options);
return FindFactory<IMultiArchiveFactory>(fileInfo).Open(fileInfos, options);
}
/// <summary>
@@ -108,7 +102,7 @@ namespace SharpCompress.Archives
firstStream.CheckNotNull(nameof(firstStream));
options ??= new ReaderOptions();
return FindArchiveFactory(firstStream).Open(streamsArray, options);
return FindFactory<IMultiArchiveFactory>(firstStream).Open(streamsArray, options);
}
/// <summary>
@@ -124,16 +118,18 @@ namespace SharpCompress.Archives
}
}
private static IArchiveFactory FindArchiveFactory(FileInfo finfo)
private static T FindFactory<T>(FileInfo finfo)
where T : IFactory
{
finfo.CheckNotNull(nameof(finfo));
using (Stream stream = finfo.OpenRead())
{
return FindArchiveFactory(stream);
return FindFactory<T>(stream);
}
}
private static IArchiveFactory FindArchiveFactory(Stream stream)
private static T FindFactory<T>(Stream stream)
where T: IFactory
{
stream.CheckNotNull(nameof(stream));
if (!stream.CanRead || !stream.CanSeek)
@@ -141,7 +137,7 @@ namespace SharpCompress.Archives
throw new ArgumentException("Stream should be readable and seekable");
}
var factores = Factories.Factory.Factories.OfType<IArchiveFactory>();
var factores = Factories.Factory.Factories.OfType<T>();
long startPosition = stream.Position;
@@ -214,21 +210,21 @@ namespace SharpCompress.Archives
public static IEnumerable<FileInfo> GetFileParts(FileInfo part1)
{
part1.CheckNotNull(nameof(part1));
yield return part1;
int i = 1;
yield return part1;
FileInfo? part = RarArchiveVolumeFactory.GetFilePart(i++, part1);
if (part != null)
foreach(var factory in Factory.Factories.OfType<IFactory>())
{
yield return part;
while ((part = RarArchiveVolumeFactory.GetFilePart(i++, part1)) != null) //tests split too
yield return part;
}
else
{
i = 1;
while ((part = ZipArchiveVolumeFactory.GetFilePart(i++, part1)) != null) //tests split too
int i = 1;
FileInfo? part = factory.GetFilePart(i++, part1);
if (part != null)
{
yield return part;
while ((part = factory.GetFilePart(i++, part1)) != null) //tests split too
yield return part;
yield break;
}
}
}
}

View File

@@ -23,8 +23,6 @@ namespace SharpCompress.Archives
/// </remarks>
public interface IArchiveFactory : IFactory
{
/// <summary>
/// Opens an Archive for random access.
/// </summary>
@@ -38,19 +36,5 @@ namespace SharpCompress.Archives
/// <param name="fileInfo">the file to open.</param>
/// <param name="readerOptions">reading options.</param>
IArchive Open(System.IO.FileInfo fileInfo, ReaderOptions? readerOptions = null);
/// <summary>
/// Constructor with IEnumerable FileInfo objects, multi and split support.
/// </summary>
/// <param name="streams"></param>
/// <param name="readerOptions">reading options.</param>
IArchive Open(IEnumerable<Stream> streams, ReaderOptions? readerOptions = null);
/// <summary>
/// Constructor with IEnumerable Stream objects, multi and split support.
/// </summary>
/// <param name="fileInfos"></param>
/// <param name="readerOptions">reading options.</param>
IArchive Open(IEnumerable<System.IO.FileInfo> fileInfos, ReaderOptions? readerOptions = null);
}
}

View File

@@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.IO;
using SharpCompress.Common;
using SharpCompress.Factories;
using SharpCompress.Readers;
namespace SharpCompress.Archives
{
/// <summary>
/// Represents a factory used to identify and open archives.
/// </summary>
/// <remarks>
/// Currently implemented by:<br/>
/// <list type="table">
/// <item><see cref="Factories.TarFactory"/></item>
/// <item><see cref="Factories.RarFactory"/></item>
/// <item><see cref="Factories.ZipFactory"/></item>
/// <item><see cref="Factories.GZipFactory"/></item>
/// <item><see cref="Factories.SevenZipFactory"/></item>
/// </list>
/// </remarks>
public interface IMultiArchiveFactory : IFactory
{
/// <summary>
/// Constructor with IEnumerable FileInfo objects, multi and split support.
/// </summary>
/// <param name="streams"></param>
/// <param name="readerOptions">reading options.</param>
IArchive Open(IEnumerable<Stream> streams, ReaderOptions? readerOptions = null);
/// <summary>
/// Constructor with IEnumerable Stream objects, multi and split support.
/// </summary>
/// <param name="fileInfos"></param>
/// <param name="readerOptions">reading options.</param>
IArchive Open(IEnumerable<System.IO.FileInfo> fileInfos, ReaderOptions? readerOptions = null);
}
}

View File

@@ -55,6 +55,12 @@ namespace SharpCompress.Factories
/// <inheritdoc/>
public abstract bool IsArchive(Stream stream, string? password = null);
/// <inheritdoc/>
public virtual FileInfo? GetFilePart(int index, FileInfo part1)
{
return null;
}
/// <summary>
/// Tries to open an <see cref="IReader"/> from a <see cref="RewindableStream"/>.
/// </summary>

View File

@@ -17,7 +17,7 @@ using SharpCompress.Writers.GZip;
namespace SharpCompress.Factories
{
public class GZipFactory : Factory, IArchiveFactory, IReaderFactory, IWriterFactory
public class GZipFactory : Factory, IArchiveFactory, IMultiArchiveFactory, IReaderFactory, IWriterFactory
{
#region IFactory
@@ -55,6 +55,10 @@ namespace SharpCompress.Factories
return GZipArchive.Open(fileInfo, readerOptions);
}
#endregion
#region IMultiArchiveFactory
/// <inheritdoc/>
public IArchive Open(IEnumerable<Stream> streams, ReaderOptions? readerOptions = null)
{

View File

@@ -40,6 +40,16 @@ namespace SharpCompress.Factories
/// <param name="stream">A stream, pointing to the beginning of the archive.</param>
/// <param name="password">optional password</param>
bool IsArchive(Stream stream, string? password = null);
/// <summary>
/// From a passed in archive (zip, rar, 7z, 001), return all parts.
/// </summary>
/// <param name="part1">Path to the first part.</param>
/// <returns>
/// The path to the requested part,
/// or NULL if the part does not exist.
/// </returns>
FileInfo? GetFilePart(int index, FileInfo part1);
}
}

View File

@@ -11,7 +11,7 @@ using SharpCompress.Readers.Rar;
namespace SharpCompress.Factories
{
public class RarFactory : Factory, IArchiveFactory, IReaderFactory
public class RarFactory : Factory, IArchiveFactory, IMultiArchiveFactory, IReaderFactory
{
#region IArchive
@@ -34,9 +34,15 @@ namespace SharpCompress.Factories
return RarArchive.IsRarFile(stream);
}
/// <inheritdoc/>
public override FileInfo? GetFilePart(int index, FileInfo part1)
{
return RarArchiveVolumeFactory.GetFilePart(index, part1);
}
#endregion
#region IArchiveFactory
#region IArchiveFactory
/// <inheritdoc/>
public IArchive Open(Stream stream, ReaderOptions? readerOptions = null)
@@ -50,6 +56,10 @@ namespace SharpCompress.Factories
return RarArchive.Open(fileInfo, readerOptions);
}
#endregion
#region IMultiArchiveFactory
/// <inheritdoc/>
public IArchive Open(IEnumerable<Stream> streams, ReaderOptions? readerOptions = null)
{

View File

@@ -5,12 +5,13 @@ using System.Linq;
using SharpCompress.Archives;
using SharpCompress.Archives.SevenZip;
using SharpCompress.Common;
using SharpCompress.Common.SevenZip;
using SharpCompress.IO;
using SharpCompress.Readers;
namespace SharpCompress.Factories
{
public class SevenZipFactory : Factory, IArchiveFactory
public class SevenZipFactory : Factory, IArchiveFactory, IMultiArchiveFactory
{
#region IFactory
@@ -34,7 +35,7 @@ namespace SharpCompress.Factories
#endregion
#region IArchiveFactory
#region IArchiveFactory
/// <inheritdoc/>
public IArchive Open(Stream stream, ReaderOptions? readerOptions = null)
@@ -48,6 +49,10 @@ namespace SharpCompress.Factories
return SevenZipArchive.Open(fileInfo, readerOptions);
}
#endregion
#region IMultiArchiveFactory
/// <inheritdoc/>
public IArchive Open(IEnumerable<Stream> streams, ReaderOptions? readerOptions = null)
{

View File

@@ -2,8 +2,10 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using SharpCompress.Archives;
using SharpCompress.Archives.Tar;
using SharpCompress.Archives.Zip;
using SharpCompress.Common;
using SharpCompress.Compressors;
using SharpCompress.Compressors.BZip2;
@@ -17,7 +19,7 @@ using SharpCompress.Writers.Tar;
namespace SharpCompress.Factories
{
public class TarFactory : Factory, IArchiveFactory, IReaderFactory, IWriterFactory
public class TarFactory : Factory, IArchiveFactory, IMultiArchiveFactory, IReaderFactory, IWriterFactory
{
#region IFactory
@@ -56,6 +58,10 @@ namespace SharpCompress.Factories
return TarArchive.Open(fileInfo, readerOptions);
}
#endregion
#region IMultiArchiveFactory
/// <inheritdoc/>
public IArchive Open(IEnumerable<Stream> streams, ReaderOptions? readerOptions = null)
{

View File

@@ -15,7 +15,7 @@ using SharpCompress.Writers.Zip;
namespace SharpCompress.Factories
{
public class ZipFactory : Factory, IArchiveFactory, IReaderFactory, IWriterFactory
public class ZipFactory : Factory, IArchiveFactory, IMultiArchiveFactory, IReaderFactory, IWriterFactory
{
#region IFactory
@@ -59,6 +59,12 @@ namespace SharpCompress.Factories
return false;
}
/// <inheritdoc/>
public override FileInfo? GetFilePart(int index, FileInfo part1)
{
return ZipArchiveVolumeFactory.GetFilePart(index, part1);
}
#endregion
#region IArchiveFactory
@@ -75,6 +81,10 @@ namespace SharpCompress.Factories
return ZipArchive.Open(fileInfo, readerOptions);
}
#endregion
#region IMultiArchiveFactory
/// <inheritdoc/>
public IArchive Open(IEnumerable<Stream> streams, ReaderOptions? readerOptions = null)
{