mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-02-18 05:25:34 +00:00
Compare commits
1 Commits
adam/rewor
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0b68146bfa |
@@ -6,6 +6,7 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Factories;
|
||||
using SharpCompress.IO;
|
||||
using SharpCompress.Readers;
|
||||
|
||||
namespace SharpCompress.Archives;
|
||||
|
||||
@@ -14,9 +14,7 @@ using SharpCompress.Writers.GZip;
|
||||
namespace SharpCompress.Archives.GZip;
|
||||
|
||||
public partial class GZipArchive
|
||||
: AbstractWritableArchive<GZipArchiveEntry, GZipVolume, GZipWriterOptions>,
|
||||
IGZipArchive,
|
||||
IGZipAsyncArchive
|
||||
: AbstractWritableArchive<GZipArchiveEntry, GZipVolume, GZipWriterOptions>
|
||||
{
|
||||
private GZipArchive(SourceStream sourceStream)
|
||||
: base(ArchiveType.GZip, sourceStream) { }
|
||||
@@ -95,10 +93,4 @@ public partial class GZipArchive
|
||||
stream.Position = 0;
|
||||
return GZipReader.OpenReader(stream, ReaderOptions);
|
||||
}
|
||||
|
||||
IEnumerable<IExtractableArchiveEntry> IExtractableArchive.Entries =>
|
||||
Entries.Cast<IExtractableArchiveEntry>();
|
||||
|
||||
IAsyncEnumerable<IExtractableArchiveEntry> IExtractableAsyncArchive.EntriesAsync =>
|
||||
EntriesAsync.CastToExtractableEntry<GZipArchiveEntry>();
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ using SharpCompress.Common.Options;
|
||||
|
||||
namespace SharpCompress.Archives.GZip;
|
||||
|
||||
public class GZipArchiveEntry : GZipEntry, IExtractableArchiveEntry
|
||||
public class GZipArchiveEntry : GZipEntry, IArchiveEntry
|
||||
{
|
||||
internal GZipArchiveEntry(GZipArchive archive, GZipFilePart? part, IReaderOptions readerOptions)
|
||||
: base(part, readerOptions) => Archive = archive;
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
using SharpCompress.Common;
|
||||
|
||||
namespace SharpCompress.Archives.GZip;
|
||||
|
||||
/// <summary>
|
||||
/// GZip archive supporting random access and entry stream extraction.
|
||||
/// </summary>
|
||||
public interface IGZipArchive : IExtractableArchive { }
|
||||
|
||||
/// <summary>
|
||||
/// Async GZip archive supporting random access and entry stream extraction.
|
||||
/// </summary>
|
||||
public interface IGZipAsyncArchive : IExtractableAsyncArchive { }
|
||||
@@ -1,9 +1,24 @@
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using SharpCompress.Common;
|
||||
|
||||
namespace SharpCompress.Archives;
|
||||
|
||||
public interface IArchiveEntry : IEntry
|
||||
{
|
||||
/// <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>
|
||||
Stream OpenEntryStream();
|
||||
|
||||
/// <summary>
|
||||
/// Opens the current entry as a stream that will decompress as it is read asynchronously.
|
||||
/// Read the entire stream or use SkipEntry on EntryStream.
|
||||
/// </summary>
|
||||
ValueTask<Stream> OpenEntryStreamAsync(CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// The archive can find all the parts of the archive needed to extract this entry.
|
||||
/// </summary>
|
||||
|
||||
@@ -12,20 +12,6 @@ public static class IArchiveEntryExtensions
|
||||
/// <param name="archiveEntry">The archive entry to extract.</param>
|
||||
extension(IArchiveEntry archiveEntry)
|
||||
{
|
||||
/// <summary>
|
||||
/// Opens the current entry as a stream that will decompress as it is read.
|
||||
/// For formats that only support sequential extraction, use archive.ExtractAllEntries().
|
||||
/// </summary>
|
||||
public Stream OpenEntryStream() => GetExtractableEntry(archiveEntry).OpenEntryStream();
|
||||
|
||||
/// <summary>
|
||||
/// Opens the current entry as a stream that will decompress as it is read asynchronously.
|
||||
/// For formats that only support sequential extraction, use archive.ExtractAllEntriesAsync().
|
||||
/// </summary>
|
||||
public ValueTask<Stream> OpenEntryStreamAsync(
|
||||
CancellationToken cancellationToken = default
|
||||
) => GetExtractableEntry(archiveEntry).OpenEntryStreamAsync(cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Extract entry to the specified stream.
|
||||
/// </summary>
|
||||
@@ -38,8 +24,7 @@ public static class IArchiveEntryExtensions
|
||||
throw new ExtractionException("Entry is a file directory and cannot be extracted.");
|
||||
}
|
||||
|
||||
var extractable = GetExtractableEntry(archiveEntry);
|
||||
using var entryStream = extractable.OpenEntryStream();
|
||||
using var entryStream = archiveEntry.OpenEntryStream();
|
||||
var sourceStream = WrapWithProgress(entryStream, archiveEntry, progress);
|
||||
sourceStream.CopyTo(streamToWriteTo, Constants.BufferSize);
|
||||
}
|
||||
@@ -62,11 +47,11 @@ public static class IArchiveEntryExtensions
|
||||
}
|
||||
|
||||
#if LEGACY_DOTNET
|
||||
using var entryStream = await GetExtractableEntry(archiveEntry)
|
||||
using var entryStream = await archiveEntry
|
||||
.OpenEntryStreamAsync(cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
#else
|
||||
await using var entryStream = await GetExtractableEntry(archiveEntry)
|
||||
await using var entryStream = await archiveEntry
|
||||
.OpenEntryStreamAsync(cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
#endif
|
||||
@@ -77,18 +62,6 @@ public static class IArchiveEntryExtensions
|
||||
}
|
||||
}
|
||||
|
||||
private static IExtractableArchiveEntry GetExtractableEntry(IArchiveEntry entry)
|
||||
{
|
||||
if (entry is IExtractableArchiveEntry extractableEntry)
|
||||
{
|
||||
return extractableEntry;
|
||||
}
|
||||
|
||||
throw new NotSupportedException(
|
||||
$"Entry stream extraction is not supported for {entry.Archive.Type} archive entries. Use archive.ExtractAllEntries() for sequential extraction."
|
||||
);
|
||||
}
|
||||
|
||||
private static Stream WrapWithProgress(
|
||||
Stream source,
|
||||
IArchiveEntry entry,
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Readers;
|
||||
|
||||
namespace SharpCompress.Archives;
|
||||
|
||||
/// <summary>
|
||||
/// Archive that supports extracting individual entries via OpenEntryStream.
|
||||
/// </summary>
|
||||
public interface IExtractableArchive : IArchive
|
||||
{
|
||||
/// <summary>
|
||||
/// Entries that support opening a decompressed content stream directly.
|
||||
/// </summary>
|
||||
new IEnumerable<IExtractableArchiveEntry> Entries { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Async archive that supports extracting individual entries via OpenEntryStream.
|
||||
/// </summary>
|
||||
public interface IExtractableAsyncArchive : IAsyncArchive
|
||||
{
|
||||
/// <summary>
|
||||
/// Entries that support opening a decompressed content stream directly.
|
||||
/// </summary>
|
||||
new IAsyncEnumerable<IExtractableArchiveEntry> EntriesAsync { get; }
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SharpCompress.Archives;
|
||||
|
||||
/// <summary>
|
||||
/// Archive entry that supports opening a decompressed content stream directly.
|
||||
/// </summary>
|
||||
public interface IExtractableArchiveEntry : IArchiveEntry
|
||||
{
|
||||
/// <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>
|
||||
Stream OpenEntryStream();
|
||||
|
||||
/// <summary>
|
||||
/// Opens the current entry as a stream that will decompress as it is read asynchronously.
|
||||
/// Read the entire stream or use SkipEntry on EntryStream.
|
||||
/// </summary>
|
||||
ValueTask<Stream> OpenEntryStreamAsync(CancellationToken cancellationToken = default);
|
||||
}
|
||||
@@ -20,9 +20,9 @@ public interface IRarArchiveCommon
|
||||
int MaxVersion { get; }
|
||||
}
|
||||
|
||||
public interface IRarArchive : IExtractableArchive, IRarArchiveCommon { }
|
||||
public interface IRarArchive : IArchive, IRarArchiveCommon { }
|
||||
|
||||
public interface IRarAsyncArchive : IExtractableAsyncArchive, IRarArchiveCommon { }
|
||||
public interface IRarAsyncArchive : IAsyncArchive, IRarArchiveCommon { }
|
||||
|
||||
public partial class RarArchive
|
||||
: AbstractArchive<RarArchiveEntry, RarVolume>,
|
||||
@@ -104,10 +104,4 @@ public partial class RarArchive
|
||||
public virtual int MinVersion => Volumes.First().MinVersion;
|
||||
|
||||
public virtual int MaxVersion => Volumes.First().MaxVersion;
|
||||
|
||||
IEnumerable<IExtractableArchiveEntry> IExtractableArchive.Entries =>
|
||||
Entries.Cast<IExtractableArchiveEntry>();
|
||||
|
||||
IAsyncEnumerable<IExtractableArchiveEntry> IExtractableAsyncArchive.EntriesAsync =>
|
||||
EntriesAsync.CastToExtractableEntry<RarArchiveEntry>();
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ using SharpCompress.Readers;
|
||||
|
||||
namespace SharpCompress.Archives.Rar;
|
||||
|
||||
public partial class RarArchiveEntry : RarEntry, IExtractableArchiveEntry
|
||||
public partial class RarArchiveEntry : RarEntry, IArchiveEntry
|
||||
{
|
||||
private readonly ICollection<RarFilePart> parts;
|
||||
private readonly RarArchive archive;
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
using SharpCompress.Common;
|
||||
|
||||
namespace SharpCompress.Archives.SevenZip;
|
||||
|
||||
/// <summary>
|
||||
/// 7Zip archive supporting metadata access and sequential extraction only.
|
||||
/// Does NOT support IExtractableArchive because 7Zip requires sequential decompression.
|
||||
/// </summary>
|
||||
public interface ISevenZipArchive : IArchive { }
|
||||
|
||||
/// <summary>
|
||||
/// Async 7Zip archive supporting metadata access and sequential extraction only.
|
||||
/// Does NOT support IExtractableAsyncArchive because 7Zip requires sequential decompression.
|
||||
/// </summary>
|
||||
public interface ISevenZipAsyncArchive : IAsyncArchive { }
|
||||
@@ -1,13 +0,0 @@
|
||||
using SharpCompress.Readers;
|
||||
|
||||
namespace SharpCompress.Archives.SevenZip;
|
||||
|
||||
/// <summary>
|
||||
/// Reader for 7Zip archives - supports sequential extraction only.
|
||||
/// </summary>
|
||||
public interface ISevenZipReader : IReader { }
|
||||
|
||||
/// <summary>
|
||||
/// Async reader for 7Zip archives - supports sequential extraction only.
|
||||
/// </summary>
|
||||
public interface ISevenZipAsyncReader : IAsyncReader { }
|
||||
@@ -12,10 +12,7 @@ using SharpCompress.Readers;
|
||||
|
||||
namespace SharpCompress.Archives.SevenZip;
|
||||
|
||||
public partial class SevenZipArchive
|
||||
: AbstractArchive<SevenZipArchiveEntry, SevenZipVolume>,
|
||||
ISevenZipArchive,
|
||||
ISevenZipAsyncArchive
|
||||
public partial class SevenZipArchive : AbstractArchive<SevenZipArchiveEntry, SevenZipVolume>
|
||||
{
|
||||
private ArchiveDatabase? _database;
|
||||
|
||||
@@ -106,10 +103,7 @@ public partial class SevenZipArchive
|
||||
public override long TotalSize =>
|
||||
_database?._packSizes.Aggregate(0L, (total, packSize) => total + packSize) ?? 0;
|
||||
|
||||
internal sealed class SevenZipReader
|
||||
: AbstractReader<SevenZipEntry, SevenZipVolume>,
|
||||
ISevenZipReader,
|
||||
ISevenZipAsyncReader
|
||||
internal sealed class SevenZipReader : AbstractReader<SevenZipEntry, SevenZipVolume>
|
||||
{
|
||||
private readonly SevenZipArchive _archive;
|
||||
private SevenZipEntry? _currentEntry;
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using SharpCompress.Common.Options;
|
||||
using SharpCompress.Common.SevenZip;
|
||||
|
||||
@@ -12,6 +15,15 @@ public class SevenZipArchiveEntry : SevenZipEntry, IArchiveEntry
|
||||
)
|
||||
: base(part, readerOptions) => Archive = archive;
|
||||
|
||||
public Stream OpenEntryStream() => FilePart.GetCompressedStream();
|
||||
|
||||
public async ValueTask<Stream> OpenEntryStreamAsync(
|
||||
CancellationToken cancellationToken = default
|
||||
) =>
|
||||
(
|
||||
await FilePart.GetCompressedStreamAsync(cancellationToken).ConfigureAwait(false)
|
||||
).NotNull();
|
||||
|
||||
public IArchive Archive { get; }
|
||||
|
||||
public bool IsComplete => true;
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
using SharpCompress.Common;
|
||||
|
||||
namespace SharpCompress.Archives.Tar;
|
||||
|
||||
/// <summary>
|
||||
/// TAR archive supporting random access and entry stream extraction.
|
||||
/// </summary>
|
||||
public interface ITarArchive : IExtractableArchive { }
|
||||
|
||||
/// <summary>
|
||||
/// Async TAR archive supporting random access and entry stream extraction.
|
||||
/// </summary>
|
||||
public interface ITarAsyncArchive : IExtractableAsyncArchive { }
|
||||
@@ -17,9 +17,7 @@ using Constants = SharpCompress.Common.Constants;
|
||||
namespace SharpCompress.Archives.Tar;
|
||||
|
||||
public partial class TarArchive
|
||||
: AbstractWritableArchive<TarArchiveEntry, TarVolume, TarWriterOptions>,
|
||||
ITarArchive,
|
||||
ITarAsyncArchive
|
||||
: AbstractWritableArchive<TarArchiveEntry, TarVolume, TarWriterOptions>
|
||||
{
|
||||
private readonly CompressionType _compressionType;
|
||||
|
||||
@@ -239,10 +237,4 @@ public partial class TarArchive
|
||||
stream.Position = 0;
|
||||
return new TarReader(stream, ReaderOptions, _compressionType);
|
||||
}
|
||||
|
||||
IEnumerable<IExtractableArchiveEntry> IExtractableArchive.Entries =>
|
||||
Entries.Cast<IExtractableArchiveEntry>();
|
||||
|
||||
IAsyncEnumerable<IExtractableArchiveEntry> IExtractableAsyncArchive.EntriesAsync =>
|
||||
EntriesAsync.CastToExtractableEntry<TarArchiveEntry>();
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ using SharpCompress.Common.Tar;
|
||||
|
||||
namespace SharpCompress.Archives.Tar;
|
||||
|
||||
public class TarArchiveEntry : TarEntry, IExtractableArchiveEntry
|
||||
public class TarArchiveEntry : TarEntry, IArchiveEntry
|
||||
{
|
||||
internal TarArchiveEntry(
|
||||
TarArchive archive,
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
using SharpCompress.Common;
|
||||
|
||||
namespace SharpCompress.Archives.Zip;
|
||||
|
||||
/// <summary>
|
||||
/// ZIP archive supporting random access and entry stream extraction.
|
||||
/// </summary>
|
||||
public interface IZipArchive : IExtractableArchive { }
|
||||
|
||||
/// <summary>
|
||||
/// Async ZIP archive supporting random access and entry stream extraction.
|
||||
/// </summary>
|
||||
public interface IZipAsyncArchive : IExtractableAsyncArchive { }
|
||||
@@ -18,9 +18,7 @@ using SharpCompress.Writers.Zip;
|
||||
namespace SharpCompress.Archives.Zip;
|
||||
|
||||
public partial class ZipArchive
|
||||
: AbstractWritableArchive<ZipArchiveEntry, ZipVolume, ZipWriterOptions>,
|
||||
IZipArchive,
|
||||
IZipAsyncArchive
|
||||
: AbstractWritableArchive<ZipArchiveEntry, ZipVolume, ZipWriterOptions>
|
||||
{
|
||||
private readonly SeekableZipHeaderFactory? headerFactory;
|
||||
|
||||
@@ -175,10 +173,4 @@ public partial class ZipArchive
|
||||
stream.Position = 0;
|
||||
return new((IAsyncReader)ZipReader.OpenReader(stream, ReaderOptions, Entries));
|
||||
}
|
||||
|
||||
IEnumerable<IExtractableArchiveEntry> IExtractableArchive.Entries =>
|
||||
Entries.Cast<IExtractableArchiveEntry>();
|
||||
|
||||
IAsyncEnumerable<IExtractableArchiveEntry> IExtractableAsyncArchive.EntriesAsync =>
|
||||
EntriesAsync.CastToExtractableEntry<ZipArchiveEntry>();
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using SharpCompress.Common.Options;
|
||||
using SharpCompress.Common.Zip;
|
||||
|
||||
namespace SharpCompress.Archives.Zip;
|
||||
|
||||
public partial class ZipArchiveEntry : ZipEntry, IExtractableArchiveEntry
|
||||
public partial class ZipArchiveEntry : ZipEntry, IArchiveEntry
|
||||
{
|
||||
internal ZipArchiveEntry(
|
||||
ZipArchive archive,
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using SharpCompress.Archives;
|
||||
|
||||
namespace SharpCompress.Common;
|
||||
|
||||
/// <summary>
|
||||
/// Extension methods for async enumerables.
|
||||
/// </summary>
|
||||
public static class AsyncEnumerableExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Casts an IAsyncEnumerable to another type.
|
||||
/// </summary>
|
||||
public static async IAsyncEnumerable<TResult> CastAsync<TResult>(
|
||||
this IAsyncEnumerable<object> source
|
||||
)
|
||||
{
|
||||
await foreach (var item in source)
|
||||
{
|
||||
yield return (TResult)item;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Casts an IAsyncEnumerable of TEntry to IAsyncEnumerable of IExtractableArchiveEntry.
|
||||
/// </summary>
|
||||
public static async IAsyncEnumerable<IExtractableArchiveEntry> CastToExtractableEntry<TEntry>(
|
||||
this IAsyncEnumerable<TEntry> source
|
||||
)
|
||||
where TEntry : IArchiveEntry
|
||||
{
|
||||
await foreach (var item in source)
|
||||
{
|
||||
yield return (IExtractableArchiveEntry)(object)item;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,10 +18,7 @@ namespace SharpCompress.Readers.Ace;
|
||||
/// - Recovery record support
|
||||
/// - Additional header flags
|
||||
/// </remarks>
|
||||
public abstract partial class AceReader
|
||||
: AbstractReader<AceEntry, AceVolume>,
|
||||
IAceReader,
|
||||
IAceAsyncReader
|
||||
public abstract partial class AceReader : AbstractReader<AceEntry, AceVolume>
|
||||
{
|
||||
private readonly IArchiveEncoding _archiveEncoding;
|
||||
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
using SharpCompress.Readers;
|
||||
|
||||
namespace SharpCompress.Readers.Ace;
|
||||
|
||||
/// <summary>
|
||||
/// Reader for ACE archives.
|
||||
/// </summary>
|
||||
public interface IAceReader : IReader { }
|
||||
|
||||
/// <summary>
|
||||
/// Async reader for ACE archives.
|
||||
/// </summary>
|
||||
public interface IAceAsyncReader : IAsyncReader { }
|
||||
@@ -9,7 +9,7 @@ using SharpCompress.Common.Arc;
|
||||
|
||||
namespace SharpCompress.Readers.Arc;
|
||||
|
||||
public partial class ArcReader : AbstractReader<ArcEntry, ArcVolume>, IArcReader, IArcAsyncReader
|
||||
public partial class ArcReader : AbstractReader<ArcEntry, ArcVolume>
|
||||
{
|
||||
private ArcReader(Stream stream, ReaderOptions options)
|
||||
: base(options, ArchiveType.Arc) => Volume = new ArcVolume(stream, options, 0);
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
using SharpCompress.Readers;
|
||||
|
||||
namespace SharpCompress.Readers.Arc;
|
||||
|
||||
/// <summary>
|
||||
/// Reader for ARC archives.
|
||||
/// </summary>
|
||||
public interface IArcReader : IReader { }
|
||||
|
||||
/// <summary>
|
||||
/// Async reader for ARC archives.
|
||||
/// </summary>
|
||||
public interface IArcAsyncReader : IAsyncReader { }
|
||||
@@ -10,10 +10,7 @@ using SharpCompress.Readers.Rar;
|
||||
|
||||
namespace SharpCompress.Readers.Arj;
|
||||
|
||||
public abstract partial class ArjReader
|
||||
: AbstractReader<ArjEntry, ArjVolume>,
|
||||
IArjReader,
|
||||
IArjAsyncReader
|
||||
public abstract partial class ArjReader : AbstractReader<ArjEntry, ArjVolume>
|
||||
{
|
||||
internal ArjReader(ReaderOptions options)
|
||||
: base(options, ArchiveType.Arj) { }
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
using SharpCompress.Readers;
|
||||
|
||||
namespace SharpCompress.Readers.Arj;
|
||||
|
||||
/// <summary>
|
||||
/// Reader for ARJ archives.
|
||||
/// </summary>
|
||||
public interface IArjReader : IReader { }
|
||||
|
||||
/// <summary>
|
||||
/// Async reader for ARJ archives.
|
||||
/// </summary>
|
||||
public interface IArjAsyncReader : IAsyncReader { }
|
||||
@@ -5,10 +5,7 @@ using SharpCompress.Common.GZip;
|
||||
|
||||
namespace SharpCompress.Readers.GZip;
|
||||
|
||||
public partial class GZipReader
|
||||
: AbstractReader<GZipEntry, GZipVolume>,
|
||||
IGZipReader,
|
||||
IGZipAsyncReader
|
||||
public partial class GZipReader : AbstractReader<GZipEntry, GZipVolume>
|
||||
{
|
||||
private GZipReader(Stream stream, ReaderOptions options)
|
||||
: base(options, ArchiveType.GZip) => Volume = new GZipVolume(stream, options, 0);
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
using SharpCompress.Readers;
|
||||
|
||||
namespace SharpCompress.Readers.GZip;
|
||||
|
||||
/// <summary>
|
||||
/// Reader for GZip archives.
|
||||
/// </summary>
|
||||
public interface IGZipReader : IReader { }
|
||||
|
||||
/// <summary>
|
||||
/// Async reader for GZip archives.
|
||||
/// </summary>
|
||||
public interface IGZipAsyncReader : IAsyncReader { }
|
||||
@@ -1,13 +0,0 @@
|
||||
using SharpCompress.Readers;
|
||||
|
||||
namespace SharpCompress.Readers.Lzw;
|
||||
|
||||
/// <summary>
|
||||
/// Reader for LZW archives.
|
||||
/// </summary>
|
||||
public interface ILzwReader : IReader { }
|
||||
|
||||
/// <summary>
|
||||
/// Async reader for LZW archives.
|
||||
/// </summary>
|
||||
public interface ILzwAsyncReader : IAsyncReader { }
|
||||
@@ -5,7 +5,7 @@ using SharpCompress.Common.Lzw;
|
||||
|
||||
namespace SharpCompress.Readers.Lzw;
|
||||
|
||||
public partial class LzwReader : AbstractReader<LzwEntry, LzwVolume>, ILzwReader, ILzwAsyncReader
|
||||
public partial class LzwReader : AbstractReader<LzwEntry, LzwVolume>
|
||||
{
|
||||
private LzwReader(Stream stream, ReaderOptions options)
|
||||
: base(options, ArchiveType.Lzw) => Volume = new LzwVolume(stream, options, 0);
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
using SharpCompress.Readers;
|
||||
|
||||
namespace SharpCompress.Readers.Rar;
|
||||
|
||||
/// <summary>
|
||||
/// Reader for RAR archives.
|
||||
/// </summary>
|
||||
public interface IRarReader : IReader { }
|
||||
|
||||
/// <summary>
|
||||
/// Async reader for RAR archives.
|
||||
/// </summary>
|
||||
public interface IRarAsyncReader : IAsyncReader { }
|
||||
@@ -11,10 +11,7 @@ namespace SharpCompress.Readers.Rar;
|
||||
/// <summary>
|
||||
/// This class faciliates Reading a Rar Archive in a non-seekable forward-only manner
|
||||
/// </summary>
|
||||
public abstract partial class RarReader
|
||||
: AbstractReader<RarReaderEntry, RarVolume>,
|
||||
IRarReader,
|
||||
IRarAsyncReader
|
||||
public abstract partial class RarReader : AbstractReader<RarReaderEntry, RarVolume>
|
||||
{
|
||||
private bool _disposed;
|
||||
private RarVolume? volume;
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
using SharpCompress.Readers;
|
||||
|
||||
namespace SharpCompress.Readers.Tar;
|
||||
|
||||
/// <summary>
|
||||
/// Reader for TAR archives.
|
||||
/// </summary>
|
||||
public interface ITarReader : IReader { }
|
||||
|
||||
/// <summary>
|
||||
/// Async reader for TAR archives.
|
||||
/// </summary>
|
||||
public interface ITarAsyncReader : IAsyncReader { }
|
||||
@@ -17,7 +17,7 @@ using SharpCompress.Providers;
|
||||
|
||||
namespace SharpCompress.Readers.Tar;
|
||||
|
||||
public partial class TarReader : AbstractReader<TarEntry, TarVolume>, ITarReader, ITarAsyncReader
|
||||
public partial class TarReader : AbstractReader<TarEntry, TarVolume>
|
||||
{
|
||||
private readonly CompressionType compressionType;
|
||||
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
using SharpCompress.Readers;
|
||||
|
||||
namespace SharpCompress.Readers.Zip;
|
||||
|
||||
/// <summary>
|
||||
/// Reader for ZIP archives.
|
||||
/// </summary>
|
||||
public interface IZipReader : IReader { }
|
||||
|
||||
/// <summary>
|
||||
/// Async reader for ZIP archives.
|
||||
/// </summary>
|
||||
public interface IZipAsyncReader : IAsyncReader { }
|
||||
@@ -9,7 +9,7 @@ using SharpCompress.Common.Zip.Headers;
|
||||
|
||||
namespace SharpCompress.Readers.Zip;
|
||||
|
||||
public partial class ZipReader : AbstractReader<ZipEntry, ZipVolume>, IZipReader, IZipAsyncReader
|
||||
public partial class ZipReader : AbstractReader<ZipEntry, ZipVolume>
|
||||
{
|
||||
private readonly StreamingZipHeaderFactory _headerFactory;
|
||||
|
||||
|
||||
@@ -216,9 +216,9 @@
|
||||
"net10.0": {
|
||||
"Microsoft.NET.ILLink.Tasks": {
|
||||
"type": "Direct",
|
||||
"requested": "[10.0.0, )",
|
||||
"resolved": "10.0.0",
|
||||
"contentHash": "kICGrGYEzCNI3wPzfEXcwNHgTvlvVn9yJDhSdRK+oZQy4jvYH529u7O0xf5ocQKzOMjfS07+3z9PKRIjrFMJDA=="
|
||||
"requested": "[10.0.2, )",
|
||||
"resolved": "10.0.2",
|
||||
"contentHash": "sXdDtMf2qcnbygw9OdE535c2lxSxrZP8gO4UhDJ0xiJbl1wIqXS1OTcTDFTIJPOFd6Mhcm8gPEthqWGUxBsTqw=="
|
||||
},
|
||||
"Microsoft.NETFramework.ReferenceAssemblies": {
|
||||
"type": "Direct",
|
||||
@@ -264,9 +264,9 @@
|
||||
"net8.0": {
|
||||
"Microsoft.NET.ILLink.Tasks": {
|
||||
"type": "Direct",
|
||||
"requested": "[8.0.22, )",
|
||||
"resolved": "8.0.22",
|
||||
"contentHash": "MhcMithKEiyyNkD2ZfbDZPmcOdi0GheGfg8saEIIEfD/fol3iHmcV8TsZkD4ZYz5gdUuoX4YtlVySUU7Sxl9SQ=="
|
||||
"requested": "[8.0.23, )",
|
||||
"resolved": "8.0.23",
|
||||
"contentHash": "GqHiB1HbbODWPbY/lc5xLQH8siEEhNA0ptpJCC6X6adtAYNEzu5ZlqV3YHA3Gh7fuEwgA8XqVwMtH2KNtuQM1Q=="
|
||||
},
|
||||
"Microsoft.NETFramework.ReferenceAssemblies": {
|
||||
"type": "Direct",
|
||||
|
||||
@@ -3,7 +3,6 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.Rar;
|
||||
using SharpCompress.Readers;
|
||||
|
||||
|
||||
@@ -25,15 +25,9 @@ public class SevenZipBenchmarks : ArchiveBenchmarkBase
|
||||
{
|
||||
using var stream = new MemoryStream(_lzmaBytes);
|
||||
using var archive = SevenZipArchive.OpenArchive(stream);
|
||||
using var reader = archive.ExtractAllEntries();
|
||||
while (reader.MoveToNextEntry())
|
||||
foreach (var entry in archive.Entries.Where(e => !e.IsDirectory))
|
||||
{
|
||||
if (reader.Entry.IsDirectory)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
using var entryStream = reader.OpenEntryStream();
|
||||
using var entryStream = entry.OpenEntryStream();
|
||||
entryStream.CopyTo(Stream.Null);
|
||||
}
|
||||
}
|
||||
@@ -45,15 +39,9 @@ public class SevenZipBenchmarks : ArchiveBenchmarkBase
|
||||
await using var archive = await SevenZipArchive
|
||||
.OpenAsyncArchive(stream)
|
||||
.ConfigureAwait(false);
|
||||
await using var reader = await archive.ExtractAllEntriesAsync().ConfigureAwait(false);
|
||||
while (await reader.MoveToNextEntryAsync().ConfigureAwait(false))
|
||||
await foreach (var entry in archive.EntriesAsync.Where(e => !e.IsDirectory))
|
||||
{
|
||||
if (reader.Entry.IsDirectory)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
await using var entryStream = await reader.OpenEntryStreamAsync().ConfigureAwait(false);
|
||||
await using var entryStream = await entry.OpenEntryStreamAsync().ConfigureAwait(false);
|
||||
await entryStream.CopyToAsync(Stream.Null).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
@@ -63,15 +51,9 @@ public class SevenZipBenchmarks : ArchiveBenchmarkBase
|
||||
{
|
||||
using var stream = new MemoryStream(_lzma2Bytes);
|
||||
using var archive = SevenZipArchive.OpenArchive(stream);
|
||||
using var reader = archive.ExtractAllEntries();
|
||||
while (reader.MoveToNextEntry())
|
||||
foreach (var entry in archive.Entries.Where(e => !e.IsDirectory))
|
||||
{
|
||||
if (reader.Entry.IsDirectory)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
using var entryStream = reader.OpenEntryStream();
|
||||
using var entryStream = entry.OpenEntryStream();
|
||||
entryStream.CopyTo(Stream.Null);
|
||||
}
|
||||
}
|
||||
@@ -83,15 +65,9 @@ public class SevenZipBenchmarks : ArchiveBenchmarkBase
|
||||
await using var archive = await SevenZipArchive
|
||||
.OpenAsyncArchive(stream)
|
||||
.ConfigureAwait(false);
|
||||
await using var reader = await archive.ExtractAllEntriesAsync().ConfigureAwait(false);
|
||||
while (await reader.MoveToNextEntryAsync().ConfigureAwait(false))
|
||||
await foreach (var entry in archive.EntriesAsync.Where(e => !e.IsDirectory))
|
||||
{
|
||||
if (reader.Entry.IsDirectory)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
await using var entryStream = await reader.OpenEntryStreamAsync().ConfigureAwait(false);
|
||||
await using var entryStream = await entry.OpenEntryStreamAsync().ConfigureAwait(false);
|
||||
await entryStream.CopyToAsync(Stream.Null).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
@@ -102,14 +78,9 @@ public class SevenZipBenchmarks : ArchiveBenchmarkBase
|
||||
using var stream = new MemoryStream(_lzma2Bytes);
|
||||
using var archive = SevenZipArchive.OpenArchive(stream);
|
||||
using var reader = archive.ExtractAllEntries();
|
||||
while (reader.MoveToNextEntry())
|
||||
foreach (var entry in archive.Entries.Where(e => !e.IsDirectory))
|
||||
{
|
||||
if (reader.Entry.IsDirectory)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
using var entryStream = reader.OpenEntryStream();
|
||||
using var entryStream = entry.OpenEntryStream();
|
||||
entryStream.CopyTo(Stream.Null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.Tar;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Compressors;
|
||||
|
||||
@@ -3,7 +3,6 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.Zip;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Compressors;
|
||||
|
||||
@@ -60,7 +60,10 @@ public class ArchiveTests : ReaderTests
|
||||
stream.ThrowOnDispose = false;
|
||||
return;
|
||||
}
|
||||
WriteArchiveEntriesToDirectory(archive, SCRATCH_FILES_PATH);
|
||||
foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory))
|
||||
{
|
||||
entry.WriteToDirectory(SCRATCH_FILES_PATH);
|
||||
}
|
||||
stream.ThrowOnDispose = false;
|
||||
}
|
||||
catch (Exception)
|
||||
@@ -143,7 +146,10 @@ public class ArchiveTests : ReaderTests
|
||||
{
|
||||
try
|
||||
{
|
||||
WriteArchiveEntriesToDirectory(archive, SCRATCH_FILES_PATH);
|
||||
foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory))
|
||||
{
|
||||
entry.WriteToDirectory(SCRATCH_FILES_PATH);
|
||||
}
|
||||
}
|
||||
catch (IndexOutOfRangeException)
|
||||
{
|
||||
@@ -178,7 +184,10 @@ public class ArchiveTests : ReaderTests
|
||||
)
|
||||
)
|
||||
{
|
||||
WriteArchiveEntriesToDirectory(archive, SCRATCH_FILES_PATH);
|
||||
foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory))
|
||||
{
|
||||
entry.WriteToDirectory(SCRATCH_FILES_PATH);
|
||||
}
|
||||
}
|
||||
VerifyFiles();
|
||||
}
|
||||
@@ -204,7 +213,10 @@ public class ArchiveTests : ReaderTests
|
||||
)
|
||||
)
|
||||
{
|
||||
WriteArchiveEntriesToDirectory(archive, SCRATCH_FILES_PATH);
|
||||
foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory))
|
||||
{
|
||||
entry.WriteToDirectory(SCRATCH_FILES_PATH);
|
||||
}
|
||||
}
|
||||
VerifyFiles();
|
||||
}
|
||||
@@ -273,7 +285,10 @@ public class ArchiveTests : ReaderTests
|
||||
ExtensionTest(testArchive, archiveFactory);
|
||||
using (var archive = archiveFactory.OpenArchive(new FileInfo(testArchive), readerOptions))
|
||||
{
|
||||
WriteArchiveEntriesToDirectory(archive, SCRATCH_FILES_PATH);
|
||||
foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory))
|
||||
{
|
||||
entry.WriteToDirectory(SCRATCH_FILES_PATH);
|
||||
}
|
||||
}
|
||||
VerifyFiles();
|
||||
}
|
||||
@@ -314,7 +329,10 @@ public class ArchiveTests : ReaderTests
|
||||
testArchive = Path.Combine(TEST_ARCHIVES_PATH, testArchive);
|
||||
using (var archive = ArchiveFactory.OpenArchive(testArchive))
|
||||
{
|
||||
WriteArchiveEntriesToDirectory(archive, SCRATCH_FILES_PATH);
|
||||
foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory))
|
||||
{
|
||||
entry.WriteToDirectory(SCRATCH_FILES_PATH);
|
||||
}
|
||||
}
|
||||
VerifyFilesEx();
|
||||
}
|
||||
@@ -323,26 +341,6 @@ public class ArchiveTests : ReaderTests
|
||||
{
|
||||
testArchive = Path.Combine(TEST_ARCHIVES_PATH, testArchive);
|
||||
using var archive = ArchiveFactory.OpenArchive(testArchive);
|
||||
|
||||
var hasNonExtractableEntries = archive.Entries.Any(entry =>
|
||||
!entry.IsDirectory && entry is not IExtractableArchiveEntry
|
||||
);
|
||||
if (hasNonExtractableEntries)
|
||||
{
|
||||
using var reader = archive.ExtractAllEntries();
|
||||
while (reader.MoveToNextEntry())
|
||||
{
|
||||
if (!reader.Entry.IsDirectory)
|
||||
{
|
||||
using var memory = new MemoryStream();
|
||||
reader.WriteEntryTo(memory);
|
||||
VerifyDeltaDistanceStream(memory);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var entry in archive.Entries)
|
||||
{
|
||||
if (!entry.IsDirectory)
|
||||
@@ -350,7 +348,17 @@ public class ArchiveTests : ReaderTests
|
||||
var memory = new MemoryStream();
|
||||
entry.WriteTo(memory);
|
||||
|
||||
VerifyDeltaDistanceStream(memory);
|
||||
memory.Position = 0;
|
||||
|
||||
for (var y = 0; y < 9; y++)
|
||||
{
|
||||
for (var x = 0; x < 256; x++)
|
||||
{
|
||||
Assert.Equal(x, memory.ReadByte());
|
||||
}
|
||||
}
|
||||
|
||||
Assert.Equal(-1, memory.ReadByte());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -405,9 +413,7 @@ public class ArchiveTests : ReaderTests
|
||||
|
||||
foreach (var entry in archive.Entries.Where(e => !e.IsDirectory))
|
||||
{
|
||||
using var entryStream = Assert
|
||||
.IsAssignableFrom<IExtractableArchiveEntry>(entry)
|
||||
.OpenEntryStream();
|
||||
using var entryStream = entry.OpenEntryStream();
|
||||
using var extractedStream = new MemoryStream();
|
||||
entryStream.CopyTo(extractedStream);
|
||||
var extractedData = extractedStream.ToArray();
|
||||
@@ -575,9 +581,7 @@ public class ArchiveTests : ReaderTests
|
||||
var entry = archive.Entries.FirstOrDefault(e => e.Key == entryName && !e.IsDirectory);
|
||||
Assert.NotNull(entry);
|
||||
|
||||
using var entryStream = Assert
|
||||
.IsAssignableFrom<IExtractableArchiveEntry>(entry)
|
||||
.OpenEntryStream();
|
||||
using var entryStream = entry.OpenEntryStream();
|
||||
using var extractedStream = new MemoryStream();
|
||||
entryStream.CopyTo(extractedStream);
|
||||
|
||||
@@ -618,7 +622,12 @@ public class ArchiveTests : ReaderTests
|
||||
{
|
||||
try
|
||||
{
|
||||
await WriteArchiveEntriesToDirectoryAsync(archive, SCRATCH_FILES_PATH);
|
||||
await foreach (
|
||||
var entry in archive.EntriesAsync.Where(entry => !entry.IsDirectory)
|
||||
)
|
||||
{
|
||||
await entry.WriteToDirectoryAsync(SCRATCH_FILES_PATH);
|
||||
}
|
||||
}
|
||||
catch (IndexOutOfRangeException)
|
||||
{
|
||||
@@ -631,67 +640,4 @@ public class ArchiveTests : ReaderTests
|
||||
VerifyFiles();
|
||||
}
|
||||
}
|
||||
|
||||
private static void VerifyDeltaDistanceStream(MemoryStream memory)
|
||||
{
|
||||
memory.Position = 0;
|
||||
|
||||
for (var y = 0; y < 9; y++)
|
||||
{
|
||||
for (var x = 0; x < 256; x++)
|
||||
{
|
||||
Assert.Equal(x, memory.ReadByte());
|
||||
}
|
||||
}
|
||||
|
||||
Assert.Equal(-1, memory.ReadByte());
|
||||
}
|
||||
|
||||
private static void WriteArchiveEntriesToDirectory(
|
||||
IArchive archive,
|
||||
string destinationDirectory
|
||||
)
|
||||
{
|
||||
if (
|
||||
archive.Entries.Any(entry =>
|
||||
!entry.IsDirectory && entry is not IExtractableArchiveEntry
|
||||
)
|
||||
)
|
||||
{
|
||||
archive.WriteToDirectory(destinationDirectory);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory))
|
||||
{
|
||||
entry.WriteToDirectory(destinationDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task WriteArchiveEntriesToDirectoryAsync(
|
||||
IAsyncArchive archive,
|
||||
string destinationDirectory
|
||||
)
|
||||
{
|
||||
var hasNonExtractableEntries = false;
|
||||
await foreach (var entry in archive.EntriesAsync)
|
||||
{
|
||||
if (!entry.IsDirectory && entry is not IExtractableArchiveEntry)
|
||||
{
|
||||
hasNonExtractableEntries = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasNonExtractableEntries)
|
||||
{
|
||||
await archive.WriteToDirectoryAsync(destinationDirectory).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
await foreach (var entry in archive.EntriesAsync.Where(entry => !entry.IsDirectory))
|
||||
{
|
||||
await entry.WriteToDirectoryAsync(destinationDirectory).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AwesomeAssertions;
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.Tar;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Common.Options;
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Threading.Tasks;
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.SevenZip;
|
||||
using SharpCompress.Readers;
|
||||
using SharpCompress.Test.Mocks;
|
||||
using Xunit;
|
||||
|
||||
namespace SharpCompress.Test.SevenZip;
|
||||
@@ -15,35 +16,215 @@ public class SevenZipArchiveAsyncTests : ArchiveTests
|
||||
public async Task SevenZipArchive_LZMA_AsyncStreamExtraction()
|
||||
{
|
||||
var testArchive = Path.Combine(TEST_ARCHIVES_PATH, "7Zip.LZMA.7z");
|
||||
await ExtractAllEntriesSequentiallyAsync(testArchive);
|
||||
#if NETFRAMEWORK
|
||||
using var stream = File.OpenRead(testArchive);
|
||||
#else
|
||||
await using var stream = File.OpenRead(testArchive);
|
||||
#endif
|
||||
await using var archive = await ArchiveFactory.OpenAsyncArchive(
|
||||
new AsyncOnlyStream(stream)
|
||||
);
|
||||
|
||||
await foreach (var entry in archive.EntriesAsync.Where(entry => !entry.IsDirectory))
|
||||
{
|
||||
var targetPath = Path.Combine(SCRATCH_FILES_PATH, entry.Key!);
|
||||
var targetDir = Path.GetDirectoryName(targetPath);
|
||||
|
||||
if (!string.IsNullOrEmpty(targetDir) && !Directory.Exists(targetDir))
|
||||
{
|
||||
Directory.CreateDirectory(targetDir);
|
||||
}
|
||||
|
||||
#if NETFRAMEWORK
|
||||
using var sourceStream = await entry.OpenEntryStreamAsync(CancellationToken.None);
|
||||
#else
|
||||
await using var sourceStream = await entry.OpenEntryStreamAsync(CancellationToken.None);
|
||||
#endif
|
||||
#if NETFRAMEWORK
|
||||
using var targetStream = File.Create(targetPath);
|
||||
#else
|
||||
await using var targetStream = File.Create(targetPath);
|
||||
#endif
|
||||
#if NETFRAMEWORK
|
||||
await sourceStream.CopyToAsync(targetStream, 81920, CancellationToken.None);
|
||||
#else
|
||||
await sourceStream.CopyToAsync(targetStream, CancellationToken.None);
|
||||
#endif
|
||||
}
|
||||
|
||||
VerifyFiles();
|
||||
}
|
||||
|
||||
//[Fact]
|
||||
public async Task SevenZipArchive_LZMA2_AsyncStreamExtraction()
|
||||
{
|
||||
var testArchive = Path.Combine(TEST_ARCHIVES_PATH, "7Zip.LZMA2.7z");
|
||||
await ExtractAllEntriesSequentiallyAsync(testArchive);
|
||||
#if NETFRAMEWORK
|
||||
using var stream = File.OpenRead(testArchive);
|
||||
#else
|
||||
await using var stream = File.OpenRead(testArchive);
|
||||
#endif
|
||||
await using var archive = await ArchiveFactory.OpenAsyncArchive(
|
||||
new AsyncOnlyStream(stream)
|
||||
);
|
||||
|
||||
await foreach (var entry in archive.EntriesAsync.Where(entry => !entry.IsDirectory))
|
||||
{
|
||||
var targetPath = Path.Combine(SCRATCH_FILES_PATH, entry.Key!);
|
||||
var targetDir = Path.GetDirectoryName(targetPath);
|
||||
|
||||
if (!string.IsNullOrEmpty(targetDir) && !Directory.Exists(targetDir))
|
||||
{
|
||||
Directory.CreateDirectory(targetDir);
|
||||
}
|
||||
|
||||
#if NETFRAMEWORK
|
||||
using var sourceStream = await entry.OpenEntryStreamAsync(CancellationToken.None);
|
||||
#else
|
||||
await using var sourceStream = await entry.OpenEntryStreamAsync(CancellationToken.None);
|
||||
#endif
|
||||
#if NETFRAMEWORK
|
||||
using var targetStream = File.Create(targetPath);
|
||||
#else
|
||||
await using var targetStream = File.Create(targetPath);
|
||||
#endif
|
||||
#if NETFRAMEWORK
|
||||
await sourceStream.CopyToAsync(targetStream, 81920, CancellationToken.None);
|
||||
#else
|
||||
await sourceStream.CopyToAsync(targetStream, CancellationToken.None);
|
||||
#endif
|
||||
}
|
||||
|
||||
VerifyFiles();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SevenZipArchive_Solid_AsyncStreamExtraction()
|
||||
{
|
||||
var testArchive = Path.Combine(TEST_ARCHIVES_PATH, "7Zip.solid.7z");
|
||||
await ExtractAllEntriesSequentiallyAsync(testArchive);
|
||||
#if NETFRAMEWORK
|
||||
using var stream = File.OpenRead(testArchive);
|
||||
#else
|
||||
await using var stream = File.OpenRead(testArchive);
|
||||
#endif
|
||||
await using var archive = await ArchiveFactory.OpenAsyncArchive(
|
||||
new AsyncOnlyStream(stream)
|
||||
);
|
||||
|
||||
await foreach (var entry in archive.EntriesAsync.Where(entry => !entry.IsDirectory))
|
||||
{
|
||||
var targetPath = Path.Combine(SCRATCH_FILES_PATH, entry.Key!);
|
||||
var targetDir = Path.GetDirectoryName(targetPath);
|
||||
|
||||
if (!string.IsNullOrEmpty(targetDir) && !Directory.Exists(targetDir))
|
||||
{
|
||||
Directory.CreateDirectory(targetDir);
|
||||
}
|
||||
|
||||
#if NETFRAMEWORK
|
||||
using var sourceStream = await entry.OpenEntryStreamAsync(CancellationToken.None);
|
||||
#else
|
||||
await using var sourceStream = await entry.OpenEntryStreamAsync(CancellationToken.None);
|
||||
#endif
|
||||
#if NETFRAMEWORK
|
||||
using var targetStream = File.Create(targetPath);
|
||||
#else
|
||||
await using var targetStream = File.Create(targetPath);
|
||||
#endif
|
||||
#if NETFRAMEWORK
|
||||
await sourceStream.CopyToAsync(targetStream, 81920, CancellationToken.None);
|
||||
#else
|
||||
await sourceStream.CopyToAsync(targetStream, CancellationToken.None);
|
||||
#endif
|
||||
}
|
||||
|
||||
VerifyFiles();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SevenZipArchive_BZip2_AsyncStreamExtraction()
|
||||
{
|
||||
var testArchive = Path.Combine(TEST_ARCHIVES_PATH, "7Zip.BZip2.7z");
|
||||
await ExtractAllEntriesSequentiallyAsync(testArchive);
|
||||
#if NETFRAMEWORK
|
||||
using var stream = File.OpenRead(testArchive);
|
||||
#else
|
||||
await using var stream = File.OpenRead(testArchive);
|
||||
#endif
|
||||
await using var archive = await ArchiveFactory.OpenAsyncArchive(
|
||||
new AsyncOnlyStream(stream)
|
||||
);
|
||||
|
||||
await foreach (var entry in archive.EntriesAsync.Where(entry => !entry.IsDirectory))
|
||||
{
|
||||
var targetPath = Path.Combine(SCRATCH_FILES_PATH, entry.Key!);
|
||||
var targetDir = Path.GetDirectoryName(targetPath);
|
||||
|
||||
if (!string.IsNullOrEmpty(targetDir) && !Directory.Exists(targetDir))
|
||||
{
|
||||
Directory.CreateDirectory(targetDir);
|
||||
}
|
||||
|
||||
#if NETFRAMEWORK
|
||||
using var sourceStream = await entry.OpenEntryStreamAsync(CancellationToken.None);
|
||||
#else
|
||||
await using var sourceStream = await entry.OpenEntryStreamAsync(CancellationToken.None);
|
||||
#endif
|
||||
#if NETFRAMEWORK
|
||||
using var targetStream = File.Create(targetPath);
|
||||
#else
|
||||
await using var targetStream = File.Create(targetPath);
|
||||
#endif
|
||||
#if NETFRAMEWORK
|
||||
await sourceStream.CopyToAsync(targetStream, 81920, CancellationToken.None);
|
||||
#else
|
||||
await sourceStream.CopyToAsync(targetStream, CancellationToken.None);
|
||||
#endif
|
||||
}
|
||||
|
||||
VerifyFiles();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SevenZipArchive_PPMd_AsyncStreamExtraction()
|
||||
{
|
||||
var testArchive = Path.Combine(TEST_ARCHIVES_PATH, "7Zip.PPMd.7z");
|
||||
await ExtractAllEntriesSequentiallyAsync(testArchive);
|
||||
#if NETFRAMEWORK
|
||||
using var stream = File.OpenRead(testArchive);
|
||||
#else
|
||||
await using var stream = File.OpenRead(testArchive);
|
||||
#endif
|
||||
await using var archive = await ArchiveFactory.OpenAsyncArchive(
|
||||
new AsyncOnlyStream(stream)
|
||||
);
|
||||
|
||||
await foreach (var entry in archive.EntriesAsync.Where(entry => !entry.IsDirectory))
|
||||
{
|
||||
var targetPath = Path.Combine(SCRATCH_FILES_PATH, entry.Key!);
|
||||
var targetDir = Path.GetDirectoryName(targetPath);
|
||||
|
||||
if (!string.IsNullOrEmpty(targetDir) && !Directory.Exists(targetDir))
|
||||
{
|
||||
Directory.CreateDirectory(targetDir);
|
||||
}
|
||||
|
||||
#if NETFRAMEWORK
|
||||
using var sourceStream = await entry.OpenEntryStreamAsync(CancellationToken.None);
|
||||
#else
|
||||
await using var sourceStream = await entry.OpenEntryStreamAsync(CancellationToken.None);
|
||||
#endif
|
||||
#if NETFRAMEWORK
|
||||
using var targetStream = File.Create(targetPath);
|
||||
#else
|
||||
await using var targetStream = File.Create(targetPath);
|
||||
#endif
|
||||
#if NETFRAMEWORK
|
||||
await sourceStream.CopyToAsync(targetStream, 81920, CancellationToken.None);
|
||||
#else
|
||||
await sourceStream.CopyToAsync(targetStream, CancellationToken.None);
|
||||
#endif
|
||||
}
|
||||
|
||||
VerifyFiles();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -136,51 +317,4 @@ public class SevenZipArchiveAsyncTests : ArchiveTests
|
||||
// The critical check: within a single folder, the stream should NEVER be recreated
|
||||
Assert.Equal(0, streamRecreationsWithinFolder); // Folder stream should remain the same for all entries in the same folder
|
||||
}
|
||||
|
||||
private async Task ExtractAllEntriesSequentiallyAsync(string testArchive)
|
||||
{
|
||||
#if NETFRAMEWORK
|
||||
using var stream = File.OpenRead(testArchive);
|
||||
#else
|
||||
await using var stream = File.OpenRead(testArchive);
|
||||
#endif
|
||||
await using var archive = await ArchiveFactory.OpenAsyncArchive(stream);
|
||||
|
||||
await using var reader = await archive.ExtractAllEntriesAsync();
|
||||
while (await reader.MoveToNextEntryAsync())
|
||||
{
|
||||
if (reader.Entry.IsDirectory)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var targetPath = Path.Combine(SCRATCH_FILES_PATH, reader.Entry.Key!);
|
||||
var targetDir = Path.GetDirectoryName(targetPath);
|
||||
|
||||
if (!string.IsNullOrEmpty(targetDir) && !Directory.Exists(targetDir))
|
||||
{
|
||||
Directory.CreateDirectory(targetDir);
|
||||
}
|
||||
|
||||
#if NETFRAMEWORK
|
||||
using var sourceStream = await reader.OpenEntryStreamAsync(CancellationToken.None);
|
||||
#else
|
||||
await using var sourceStream = await reader.OpenEntryStreamAsync(
|
||||
CancellationToken.None
|
||||
);
|
||||
#endif
|
||||
#if NETFRAMEWORK
|
||||
using var targetStream = File.Create(targetPath);
|
||||
#else
|
||||
await using var targetStream = File.Create(targetPath);
|
||||
#endif
|
||||
#if NETFRAMEWORK
|
||||
await sourceStream.CopyToAsync(targetStream, 81920, CancellationToken.None);
|
||||
#else
|
||||
await sourceStream.CopyToAsync(targetStream, CancellationToken.None);
|
||||
#endif
|
||||
}
|
||||
|
||||
VerifyFiles();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,11 +209,8 @@ public class SevenZipArchiveTests : ArchiveTests
|
||||
using (Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "7Zip.Tar.tar.7z")))
|
||||
using (var archive = SevenZipArchive.OpenArchive(stream))
|
||||
{
|
||||
using var reader = archive.ExtractAllEntries();
|
||||
Assert.True(reader.MoveToNextEntry());
|
||||
reader.WriteEntryToDirectory(SCRATCH_FILES_PATH);
|
||||
|
||||
var entry = archive.Entries.First();
|
||||
entry.WriteToFile(Path.Combine(SCRATCH_FILES_PATH, entry.Key.NotNull()));
|
||||
|
||||
var size = entry.Size;
|
||||
var scratch = new FileInfo(Path.Combine(SCRATCH_FILES_PATH, "7Zip.Tar.tar"));
|
||||
@@ -369,12 +366,12 @@ public class SevenZipArchiveTests : ArchiveTests
|
||||
{
|
||||
emptyStreamFileCount++;
|
||||
}
|
||||
|
||||
// This should not throw NullReferenceException
|
||||
entry.WriteToDirectory(SCRATCH_FILES_PATH);
|
||||
}
|
||||
}
|
||||
|
||||
// Use archive-level extraction for SevenZip since entries don't support direct stream extraction
|
||||
archive.WriteToDirectory(SCRATCH_FILES_PATH);
|
||||
|
||||
// Ensure we actually tested empty-stream entries
|
||||
Assert.True(
|
||||
emptyStreamFileCount > 0,
|
||||
|
||||
@@ -3,7 +3,6 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.Zip;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Compressors.Deflate;
|
||||
|
||||
@@ -2,7 +2,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.Zip;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Compressors.Deflate;
|
||||
|
||||
Reference in New Issue
Block a user