mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-09-24 07:54:39 +00:00
Merge pull request #1189 from adamhathcock/copilot/add-lzwreader-support
Add LzwReader support for .Z compressed archives
This commit is contained in:
@@ -69,7 +69,7 @@ public static partial class ArchiveFactory
|
||||
options ??= ReaderOptions.ForOwnedFile;
|
||||
|
||||
var factory = await FindFactoryAsync<IMultiArchiveFactory>(fileInfo, cancellationToken);
|
||||
return factory.OpenAsyncArchive(filesArray, options, cancellationToken);
|
||||
return factory.OpenAsyncArchive(filesArray, options);
|
||||
}
|
||||
|
||||
public static async ValueTask<IAsyncArchive> OpenAsyncArchive(
|
||||
|
||||
@@ -22,11 +22,9 @@ public partial class GZipArchive
|
||||
{
|
||||
public static IWritableAsyncArchive<GZipWriterOptions> OpenAsyncArchive(
|
||||
string path,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
ReaderOptions? readerOptions = null
|
||||
)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
path.NotNullOrEmpty(nameof(path));
|
||||
return (IWritableAsyncArchive<GZipWriterOptions>)
|
||||
OpenArchive(new FileInfo(path), readerOptions ?? new ReaderOptions());
|
||||
@@ -107,43 +105,23 @@ public partial class GZipArchive
|
||||
|
||||
public static IWritableAsyncArchive<GZipWriterOptions> OpenAsyncArchive(
|
||||
Stream stream,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IWritableAsyncArchive<GZipWriterOptions>)OpenArchive(stream, readerOptions);
|
||||
}
|
||||
ReaderOptions? readerOptions = null
|
||||
) => (IWritableAsyncArchive<GZipWriterOptions>)OpenArchive(stream, readerOptions);
|
||||
|
||||
public static IWritableAsyncArchive<GZipWriterOptions> OpenAsyncArchive(
|
||||
FileInfo fileInfo,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IWritableAsyncArchive<GZipWriterOptions>)OpenArchive(fileInfo, readerOptions);
|
||||
}
|
||||
ReaderOptions? readerOptions = null
|
||||
) => (IWritableAsyncArchive<GZipWriterOptions>)OpenArchive(fileInfo, readerOptions);
|
||||
|
||||
public static IWritableAsyncArchive<GZipWriterOptions> OpenAsyncArchive(
|
||||
IReadOnlyList<Stream> streams,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IWritableAsyncArchive<GZipWriterOptions>)OpenArchive(streams, readerOptions);
|
||||
}
|
||||
ReaderOptions? readerOptions = null
|
||||
) => (IWritableAsyncArchive<GZipWriterOptions>)OpenArchive(streams, readerOptions);
|
||||
|
||||
public static IWritableAsyncArchive<GZipWriterOptions> OpenAsyncArchive(
|
||||
IReadOnlyList<FileInfo> fileInfos,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IWritableAsyncArchive<GZipWriterOptions>)OpenArchive(fileInfos, readerOptions);
|
||||
}
|
||||
ReaderOptions? readerOptions = null
|
||||
) => (IWritableAsyncArchive<GZipWriterOptions>)OpenArchive(fileInfos, readerOptions);
|
||||
|
||||
public static IWritableArchive<GZipWriterOptions> CreateArchive() => new GZipArchive();
|
||||
|
||||
|
||||
@@ -20,20 +20,17 @@ public interface IArchiveOpenable<TSync, TASync>
|
||||
|
||||
public static abstract TASync OpenAsyncArchive(
|
||||
string path,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
ReaderOptions? readerOptions = null
|
||||
);
|
||||
|
||||
public static abstract TASync OpenAsyncArchive(
|
||||
Stream stream,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
ReaderOptions? readerOptions = null
|
||||
);
|
||||
|
||||
public static abstract TASync OpenAsyncArchive(
|
||||
FileInfo fileInfo,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
ReaderOptions? readerOptions = null
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -50,10 +50,8 @@ public interface IMultiArchiveFactory : IFactory
|
||||
/// </summary>
|
||||
/// <param name="fileInfos"></param>
|
||||
/// <param name="readerOptions">reading options.</param>
|
||||
/// <param name="cancellationToken">Cancellation token.</param>
|
||||
IAsyncArchive OpenAsyncArchive(
|
||||
IReadOnlyList<FileInfo> fileInfos,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
ReaderOptions? readerOptions = null
|
||||
);
|
||||
}
|
||||
|
||||
@@ -22,14 +22,12 @@ public interface IMultiArchiveOpenable<TSync, TASync>
|
||||
|
||||
public static abstract TASync OpenAsyncArchive(
|
||||
IReadOnlyList<Stream> streams,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
ReaderOptions? readerOptions = null
|
||||
);
|
||||
|
||||
public static abstract TASync OpenAsyncArchive(
|
||||
IReadOnlyList<FileInfo> fileInfos,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
ReaderOptions? readerOptions = null
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -22,11 +22,9 @@ public partial class RarArchive
|
||||
{
|
||||
public static IRarAsyncArchive OpenAsyncArchive(
|
||||
string path,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
ReaderOptions? readerOptions = null
|
||||
)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
path.NotNullOrEmpty(nameof(path));
|
||||
return (IRarAsyncArchive)OpenArchive(new FileInfo(path), readerOptions);
|
||||
}
|
||||
@@ -102,41 +100,33 @@ public partial class RarArchive
|
||||
|
||||
public static IRarAsyncArchive OpenAsyncArchive(
|
||||
Stream stream,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
ReaderOptions? readerOptions = null
|
||||
)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IRarAsyncArchive)OpenArchive(stream, readerOptions);
|
||||
}
|
||||
|
||||
public static IRarAsyncArchive OpenAsyncArchive(
|
||||
FileInfo fileInfo,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
ReaderOptions? readerOptions = null
|
||||
)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IRarAsyncArchive)OpenArchive(fileInfo, readerOptions);
|
||||
}
|
||||
|
||||
public static IRarAsyncArchive OpenAsyncArchive(
|
||||
IReadOnlyList<Stream> streams,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
ReaderOptions? readerOptions = null
|
||||
)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IRarAsyncArchive)OpenArchive(streams, readerOptions);
|
||||
}
|
||||
|
||||
public static IRarAsyncArchive OpenAsyncArchive(
|
||||
IReadOnlyList<FileInfo> fileInfos,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
ReaderOptions? readerOptions = null
|
||||
)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IRarAsyncArchive)OpenArchive(fileInfos, readerOptions);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,13 +16,8 @@ public partial class SevenZipArchive
|
||||
IMultiArchiveOpenable<IArchive, IAsyncArchive>
|
||||
#endif
|
||||
{
|
||||
public static IAsyncArchive OpenAsyncArchive(
|
||||
string path,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
public static IAsyncArchive OpenAsyncArchive(string path, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
path.NotNullOrEmpty("path");
|
||||
return (IAsyncArchive)OpenArchive(new FileInfo(path), readerOptions ?? new ReaderOptions());
|
||||
}
|
||||
@@ -91,43 +86,32 @@ public partial class SevenZipArchive
|
||||
);
|
||||
}
|
||||
|
||||
public static IAsyncArchive OpenAsyncArchive(
|
||||
Stream stream,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
public static IAsyncArchive OpenAsyncArchive(Stream stream, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IAsyncArchive)OpenArchive(stream, readerOptions);
|
||||
}
|
||||
|
||||
public static IAsyncArchive OpenAsyncArchive(
|
||||
FileInfo fileInfo,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
ReaderOptions? readerOptions = null
|
||||
)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IAsyncArchive)OpenArchive(fileInfo, readerOptions);
|
||||
}
|
||||
|
||||
public static IAsyncArchive OpenAsyncArchive(
|
||||
IReadOnlyList<Stream> streams,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
ReaderOptions? readerOptions = null
|
||||
)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IAsyncArchive)OpenArchive(streams, readerOptions);
|
||||
}
|
||||
|
||||
public static IAsyncArchive OpenAsyncArchive(
|
||||
IReadOnlyList<FileInfo> fileInfos,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
ReaderOptions? readerOptions = null
|
||||
)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IAsyncArchive)OpenArchive(fileInfos, readerOptions);
|
||||
}
|
||||
|
||||
|
||||
@@ -97,54 +97,28 @@ public partial class TarArchive
|
||||
|
||||
public static IWritableAsyncArchive<TarWriterOptions> OpenAsyncArchive(
|
||||
Stream stream,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IWritableAsyncArchive<TarWriterOptions>)OpenArchive(stream, readerOptions);
|
||||
}
|
||||
ReaderOptions? readerOptions = null
|
||||
) => (IWritableAsyncArchive<TarWriterOptions>)OpenArchive(stream, readerOptions);
|
||||
|
||||
public static IWritableAsyncArchive<TarWriterOptions> OpenAsyncArchive(
|
||||
string path,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IWritableAsyncArchive<TarWriterOptions>)
|
||||
OpenArchive(new FileInfo(path), readerOptions);
|
||||
}
|
||||
ReaderOptions? readerOptions = null
|
||||
) => (IWritableAsyncArchive<TarWriterOptions>)OpenArchive(new FileInfo(path), readerOptions);
|
||||
|
||||
public static IWritableAsyncArchive<TarWriterOptions> OpenAsyncArchive(
|
||||
FileInfo fileInfo,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IWritableAsyncArchive<TarWriterOptions>)OpenArchive(fileInfo, readerOptions);
|
||||
}
|
||||
ReaderOptions? readerOptions = null
|
||||
) => (IWritableAsyncArchive<TarWriterOptions>)OpenArchive(fileInfo, readerOptions);
|
||||
|
||||
public static IWritableAsyncArchive<TarWriterOptions> OpenAsyncArchive(
|
||||
IReadOnlyList<Stream> streams,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IWritableAsyncArchive<TarWriterOptions>)OpenArchive(streams, readerOptions);
|
||||
}
|
||||
ReaderOptions? readerOptions = null
|
||||
) => (IWritableAsyncArchive<TarWriterOptions>)OpenArchive(streams, readerOptions);
|
||||
|
||||
public static IWritableAsyncArchive<TarWriterOptions> OpenAsyncArchive(
|
||||
IReadOnlyList<FileInfo> fileInfos,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IWritableAsyncArchive<TarWriterOptions>)OpenArchive(fileInfos, readerOptions);
|
||||
}
|
||||
ReaderOptions? readerOptions = null
|
||||
) => (IWritableAsyncArchive<TarWriterOptions>)OpenArchive(fileInfos, readerOptions);
|
||||
|
||||
public static bool IsTarFile(string filePath) => IsTarFile(new FileInfo(filePath));
|
||||
|
||||
|
||||
@@ -97,53 +97,28 @@ public partial class ZipArchive
|
||||
|
||||
public static IWritableAsyncArchive<ZipWriterOptions> OpenAsyncArchive(
|
||||
string path,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IWritableAsyncArchive<ZipWriterOptions>)OpenArchive(path, readerOptions);
|
||||
}
|
||||
ReaderOptions? readerOptions = null
|
||||
) => (IWritableAsyncArchive<ZipWriterOptions>)OpenArchive(path, readerOptions);
|
||||
|
||||
public static IWritableAsyncArchive<ZipWriterOptions> OpenAsyncArchive(
|
||||
Stream stream,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IWritableAsyncArchive<ZipWriterOptions>)OpenArchive(stream, readerOptions);
|
||||
}
|
||||
ReaderOptions? readerOptions = null
|
||||
) => (IWritableAsyncArchive<ZipWriterOptions>)OpenArchive(stream, readerOptions);
|
||||
|
||||
public static IWritableAsyncArchive<ZipWriterOptions> OpenAsyncArchive(
|
||||
FileInfo fileInfo,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IWritableAsyncArchive<ZipWriterOptions>)OpenArchive(fileInfo, readerOptions);
|
||||
}
|
||||
ReaderOptions? readerOptions = null
|
||||
) => (IWritableAsyncArchive<ZipWriterOptions>)OpenArchive(fileInfo, readerOptions);
|
||||
|
||||
public static IWritableAsyncArchive<ZipWriterOptions> OpenAsyncArchive(
|
||||
IReadOnlyList<Stream> streams,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IWritableAsyncArchive<ZipWriterOptions>)OpenArchive(streams, readerOptions);
|
||||
}
|
||||
ReaderOptions? readerOptions = null
|
||||
) => (IWritableAsyncArchive<ZipWriterOptions>)OpenArchive(streams, readerOptions);
|
||||
|
||||
public static IWritableAsyncArchive<ZipWriterOptions> OpenAsyncArchive(
|
||||
IReadOnlyList<FileInfo> fileInfos,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IWritableAsyncArchive<ZipWriterOptions>)OpenArchive(fileInfos, readerOptions);
|
||||
}
|
||||
ReaderOptions? readerOptions = null
|
||||
) => (IWritableAsyncArchive<ZipWriterOptions>)OpenArchive(fileInfos, readerOptions);
|
||||
|
||||
public static bool IsZipFile(string filePath, string? password = null) =>
|
||||
IsZipFile(new FileInfo(filePath), password);
|
||||
|
||||
@@ -10,4 +10,5 @@ public enum ArchiveType
|
||||
Arc,
|
||||
Arj,
|
||||
Ace,
|
||||
Lzw,
|
||||
}
|
||||
|
||||
22
src/SharpCompress/Common/Lzw/LzwEntry.Async.cs
Normal file
22
src/SharpCompress/Common/Lzw/LzwEntry.Async.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
using SharpCompress.Readers;
|
||||
|
||||
namespace SharpCompress.Common.Lzw;
|
||||
|
||||
public partial class LzwEntry
|
||||
{
|
||||
internal static async IAsyncEnumerable<LzwEntry> GetEntriesAsync(
|
||||
Stream stream,
|
||||
ReaderOptions options,
|
||||
[EnumeratorCancellation] CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
yield return new LzwEntry(
|
||||
await LzwFilePart.CreateAsync(stream, options.ArchiveEncoding, cancellationToken),
|
||||
options
|
||||
);
|
||||
}
|
||||
}
|
||||
53
src/SharpCompress/Common/Lzw/LzwEntry.cs
Normal file
53
src/SharpCompress/Common/Lzw/LzwEntry.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SharpCompress.Common.Options;
|
||||
using SharpCompress.Readers;
|
||||
|
||||
namespace SharpCompress.Common.Lzw;
|
||||
|
||||
public partial class LzwEntry : Entry
|
||||
{
|
||||
private readonly LzwFilePart? _filePart;
|
||||
|
||||
internal LzwEntry(LzwFilePart? filePart, IReaderOptions readerOptions)
|
||||
: base(readerOptions)
|
||||
{
|
||||
_filePart = filePart;
|
||||
}
|
||||
|
||||
public override CompressionType CompressionType => CompressionType.Lzw;
|
||||
|
||||
public override long Crc => 0;
|
||||
|
||||
public override string? Key => _filePart?.FilePartName;
|
||||
|
||||
public override string? LinkTarget => null;
|
||||
|
||||
public override long CompressedSize => 0;
|
||||
|
||||
public override long Size => 0;
|
||||
|
||||
public override DateTime? LastModifiedTime => null;
|
||||
|
||||
public override DateTime? CreatedTime => null;
|
||||
|
||||
public override DateTime? LastAccessedTime => null;
|
||||
|
||||
public override DateTime? ArchivedTime => null;
|
||||
|
||||
public override bool IsEncrypted => false;
|
||||
|
||||
public override bool IsDirectory => false;
|
||||
|
||||
public override bool IsSplitAfter => false;
|
||||
|
||||
internal override IEnumerable<FilePart> Parts => _filePart.Empty();
|
||||
|
||||
internal static IEnumerable<LzwEntry> GetEntries(Stream stream, ReaderOptions options)
|
||||
{
|
||||
yield return new LzwEntry(LzwFilePart.Create(stream, options.ArchiveEncoding), options);
|
||||
}
|
||||
|
||||
// Async methods moved to LzwEntry.Async.cs
|
||||
}
|
||||
23
src/SharpCompress/Common/Lzw/LzwFilePart.Async.cs
Normal file
23
src/SharpCompress/Common/Lzw/LzwFilePart.Async.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SharpCompress.Common.Lzw;
|
||||
|
||||
internal sealed partial class LzwFilePart
|
||||
{
|
||||
internal static async ValueTask<LzwFilePart> CreateAsync(
|
||||
Stream stream,
|
||||
IArchiveEncoding archiveEncoding,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
var part = new LzwFilePart(stream, archiveEncoding);
|
||||
|
||||
// For non-seekable streams, we can't track position, so use 0 since the stream will be
|
||||
// read sequentially from its current position.
|
||||
part.EntryStartPosition = stream.CanSeek ? stream.Position : 0;
|
||||
return part;
|
||||
}
|
||||
}
|
||||
60
src/SharpCompress/Common/Lzw/LzwFilePart.cs
Normal file
60
src/SharpCompress/Common/Lzw/LzwFilePart.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
using System.IO;
|
||||
using SharpCompress.Compressors.Lzw;
|
||||
|
||||
namespace SharpCompress.Common.Lzw;
|
||||
|
||||
internal sealed partial class LzwFilePart : FilePart
|
||||
{
|
||||
private readonly Stream _stream;
|
||||
private readonly string? _name;
|
||||
|
||||
internal static LzwFilePart Create(Stream stream, IArchiveEncoding archiveEncoding)
|
||||
{
|
||||
var part = new LzwFilePart(stream, archiveEncoding);
|
||||
|
||||
// For non-seekable streams, we can't track position, so use 0 since the stream will be
|
||||
// read sequentially from its current position.
|
||||
part.EntryStartPosition = stream.CanSeek ? stream.Position : 0;
|
||||
return part;
|
||||
}
|
||||
|
||||
private LzwFilePart(Stream stream, IArchiveEncoding archiveEncoding)
|
||||
: base(archiveEncoding)
|
||||
{
|
||||
_stream = stream;
|
||||
_name = DeriveFileName(stream);
|
||||
}
|
||||
|
||||
internal long EntryStartPosition { get; private set; }
|
||||
|
||||
internal override string? FilePartName => _name;
|
||||
|
||||
internal override Stream GetCompressedStream() =>
|
||||
new LzwStream(_stream) { IsStreamOwner = false };
|
||||
|
||||
internal override Stream GetRawStream() => _stream;
|
||||
|
||||
private static string? DeriveFileName(Stream stream)
|
||||
{
|
||||
// Unwrap SharpCompressStream to get to the underlying FileStream
|
||||
var unwrappedStream = stream;
|
||||
if (stream is SharpCompress.IO.IStreamStack streamStack)
|
||||
{
|
||||
unwrappedStream = streamStack.BaseStream();
|
||||
}
|
||||
|
||||
// Try to derive filename from FileStream
|
||||
if (unwrappedStream is FileStream fileStream && !string.IsNullOrEmpty(fileStream.Name))
|
||||
{
|
||||
var fileName = Path.GetFileName(fileStream.Name);
|
||||
// Strip .Z extension if present
|
||||
if (fileName.EndsWith(".Z", System.StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return fileName.Substring(0, fileName.Length - 2);
|
||||
}
|
||||
return fileName;
|
||||
}
|
||||
// Default name for non-file streams
|
||||
return "data";
|
||||
}
|
||||
}
|
||||
17
src/SharpCompress/Common/Lzw/LzwVolume.cs
Normal file
17
src/SharpCompress/Common/Lzw/LzwVolume.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System.IO;
|
||||
using SharpCompress.Readers;
|
||||
|
||||
namespace SharpCompress.Common.Lzw;
|
||||
|
||||
public class LzwVolume : Volume
|
||||
{
|
||||
public LzwVolume(Stream stream, ReaderOptions? options, int index)
|
||||
: base(stream, options, index) { }
|
||||
|
||||
public LzwVolume(FileInfo fileInfo, ReaderOptions options)
|
||||
: base(fileInfo.OpenRead(), options with { LeaveStreamOpen = false }) { }
|
||||
|
||||
public override bool IsFirstVolume => true;
|
||||
|
||||
public override bool IsMultiVolume => false;
|
||||
}
|
||||
@@ -18,6 +18,7 @@ public abstract class Factory : IFactory
|
||||
RegisterFactory(new RarFactory());
|
||||
RegisterFactory(new TarFactory()); //put tar before most
|
||||
RegisterFactory(new GZipFactory());
|
||||
RegisterFactory(new LzwFactory());
|
||||
RegisterFactory(new ArcFactory());
|
||||
RegisterFactory(new ArjFactory());
|
||||
RegisterFactory(new AceFactory());
|
||||
|
||||
@@ -95,13 +95,8 @@ public class GZipFactory
|
||||
/// <inheritdoc/>
|
||||
public IAsyncArchive OpenAsyncArchive(
|
||||
IReadOnlyList<FileInfo> fileInfos,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IAsyncArchive)OpenArchive(fileInfos, readerOptions);
|
||||
}
|
||||
ReaderOptions? readerOptions = null
|
||||
) => (IAsyncArchive)OpenArchive(fileInfos, readerOptions);
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
94
src/SharpCompress/Factories/LzwFactory.cs
Normal file
94
src/SharpCompress/Factories/LzwFactory.cs
Normal file
@@ -0,0 +1,94 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using SharpCompress.Archives.Tar;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Compressors.Lzw;
|
||||
using SharpCompress.IO;
|
||||
using SharpCompress.Readers;
|
||||
using SharpCompress.Readers.Lzw;
|
||||
using SharpCompress.Readers.Tar;
|
||||
|
||||
namespace SharpCompress.Factories;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the foundation factory of LZW archive.
|
||||
/// </summary>
|
||||
public class LzwFactory : Factory, IReaderFactory
|
||||
{
|
||||
#region IFactory
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string Name => "Lzw";
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override ArchiveType? KnownArchiveType => ArchiveType.Lzw;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override IEnumerable<string> GetSupportedExtensions()
|
||||
{
|
||||
yield return "z";
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool IsArchive(Stream stream, string? password = null) =>
|
||||
LzwStream.IsLzwStream(stream);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override ValueTask<bool> IsArchiveAsync(
|
||||
Stream stream,
|
||||
string? password = null,
|
||||
CancellationToken cancellationToken = default
|
||||
) => LzwStream.IsLzwStreamAsync(stream, cancellationToken);
|
||||
|
||||
#endregion
|
||||
|
||||
#region IReaderFactory
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal override bool TryOpenReader(
|
||||
SharpCompressStream sharpCompressStream,
|
||||
ReaderOptions options,
|
||||
out IReader? reader
|
||||
)
|
||||
{
|
||||
reader = null;
|
||||
|
||||
if (LzwStream.IsLzwStream(sharpCompressStream))
|
||||
{
|
||||
sharpCompressStream.Rewind();
|
||||
using (var testStream = new LzwStream(sharpCompressStream) { IsStreamOwner = false })
|
||||
{
|
||||
if (TarArchive.IsTarFile(testStream))
|
||||
{
|
||||
sharpCompressStream.StopRecording();
|
||||
reader = new TarReader(sharpCompressStream, options, CompressionType.Lzw);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
sharpCompressStream.StopRecording();
|
||||
reader = OpenReader(sharpCompressStream, options);
|
||||
return true;
|
||||
}
|
||||
sharpCompressStream.Rewind();
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IReader OpenReader(Stream stream, ReaderOptions? options) =>
|
||||
LzwReader.OpenReader(stream, options);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ValueTask<IAsyncReader> OpenAsyncReader(
|
||||
Stream stream,
|
||||
ReaderOptions? options,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return new(LzwReader.OpenAsyncReader(stream, options));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -90,11 +90,9 @@ public class RarFactory : Factory, IArchiveFactory, IMultiArchiveFactory, IReade
|
||||
/// <inheritdoc/>
|
||||
public IAsyncArchive OpenAsyncArchive(
|
||||
IReadOnlyList<FileInfo> fileInfos,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
ReaderOptions? readerOptions = null
|
||||
)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IAsyncArchive)OpenArchive(fileInfos, readerOptions);
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ public class SevenZipFactory : Factory, IArchiveFactory, IMultiArchiveFactory
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IAsyncArchive OpenAsyncArchive(Stream stream, ReaderOptions? readerOptions = null) =>
|
||||
SevenZipArchive.OpenAsyncArchive(stream, readerOptions, CancellationToken.None);
|
||||
SevenZipArchive.OpenAsyncArchive(stream, readerOptions);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive OpenArchive(FileInfo fileInfo, ReaderOptions? readerOptions = null) =>
|
||||
@@ -58,7 +58,7 @@ public class SevenZipFactory : Factory, IArchiveFactory, IMultiArchiveFactory
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IAsyncArchive OpenAsyncArchive(FileInfo fileInfo, ReaderOptions? readerOptions = null) =>
|
||||
SevenZipArchive.OpenAsyncArchive(fileInfo, readerOptions, CancellationToken.None);
|
||||
SevenZipArchive.OpenAsyncArchive(fileInfo, readerOptions);
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -74,7 +74,7 @@ public class SevenZipFactory : Factory, IArchiveFactory, IMultiArchiveFactory
|
||||
public IAsyncArchive OpenAsyncArchive(
|
||||
IReadOnlyList<Stream> streams,
|
||||
ReaderOptions? readerOptions = null
|
||||
) => SevenZipArchive.OpenAsyncArchive(streams, readerOptions, CancellationToken.None);
|
||||
) => SevenZipArchive.OpenAsyncArchive(streams, readerOptions);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IArchive OpenArchive(
|
||||
@@ -85,9 +85,8 @@ public class SevenZipFactory : Factory, IArchiveFactory, IMultiArchiveFactory
|
||||
/// <inheritdoc/>
|
||||
public IAsyncArchive OpenAsyncArchive(
|
||||
IReadOnlyList<FileInfo> fileInfos,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
) => SevenZipArchive.OpenAsyncArchive(fileInfos, readerOptions, cancellationToken);
|
||||
ReaderOptions? readerOptions = null
|
||||
) => SevenZipArchive.OpenAsyncArchive(fileInfos, readerOptions);
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -145,13 +145,8 @@ public class TarFactory
|
||||
/// <inheritdoc/>
|
||||
public IAsyncArchive OpenAsyncArchive(
|
||||
IReadOnlyList<FileInfo> fileInfos,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IAsyncArchive)OpenArchive(fileInfos, readerOptions);
|
||||
}
|
||||
ReaderOptions? readerOptions = null
|
||||
) => (IAsyncArchive)OpenArchive(fileInfos, readerOptions);
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -155,13 +155,8 @@ public class ZipFactory
|
||||
/// <inheritdoc/>
|
||||
public IAsyncArchive OpenAsyncArchive(
|
||||
IReadOnlyList<FileInfo> fileInfos,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IAsyncArchive)OpenArchive(fileInfos, readerOptions);
|
||||
}
|
||||
ReaderOptions? readerOptions = null
|
||||
) => (IAsyncArchive)OpenArchive(fileInfos, readerOptions);
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using SharpCompress.Common;
|
||||
|
||||
namespace SharpCompress.Readers.Ace;
|
||||
@@ -34,24 +33,14 @@ public partial class AceReader
|
||||
return new MultiVolumeAceReader(streams, options ?? new ReaderOptions());
|
||||
}
|
||||
|
||||
public static IAsyncReader OpenAsyncReader(
|
||||
string path,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
public static IAsyncReader OpenAsyncReader(string path, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
path.NotNullOrEmpty(nameof(path));
|
||||
return (IAsyncReader)OpenReader(new FileInfo(path), readerOptions);
|
||||
}
|
||||
|
||||
public static IAsyncReader OpenAsyncReader(
|
||||
Stream stream,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
public static IAsyncReader OpenAsyncReader(Stream stream, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IAsyncReader)OpenReader(stream, readerOptions);
|
||||
}
|
||||
|
||||
@@ -66,11 +55,9 @@ public partial class AceReader
|
||||
|
||||
public static IAsyncReader OpenAsyncReader(
|
||||
FileInfo fileInfo,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
ReaderOptions? readerOptions = null
|
||||
)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IAsyncReader)OpenReader(fileInfo, readerOptions);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,40 +1,27 @@
|
||||
#if NET8_0_OR_GREATER
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using SharpCompress.Common;
|
||||
|
||||
namespace SharpCompress.Readers.Arc;
|
||||
|
||||
public partial class ArcReader : IReaderOpenable
|
||||
{
|
||||
public static IAsyncReader OpenAsyncReader(
|
||||
string path,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
public static IAsyncReader OpenAsyncReader(string path, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
path.NotNullOrEmpty(nameof(path));
|
||||
return (IAsyncReader)OpenReader(new FileInfo(path), readerOptions);
|
||||
}
|
||||
|
||||
public static IAsyncReader OpenAsyncReader(
|
||||
Stream stream,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
public static IAsyncReader OpenAsyncReader(Stream stream, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IAsyncReader)OpenReader(stream, readerOptions);
|
||||
}
|
||||
|
||||
public static IAsyncReader OpenAsyncReader(
|
||||
FileInfo fileInfo,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
ReaderOptions? readerOptions = null
|
||||
)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IAsyncReader)OpenReader(fileInfo, readerOptions);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,40 +1,27 @@
|
||||
#if NET8_0_OR_GREATER
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using SharpCompress.Common;
|
||||
|
||||
namespace SharpCompress.Readers.Arj;
|
||||
|
||||
public partial class ArjReader : IReaderOpenable
|
||||
{
|
||||
public static IAsyncReader OpenAsyncReader(
|
||||
string path,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
public static IAsyncReader OpenAsyncReader(string path, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
path.NotNullOrEmpty(nameof(path));
|
||||
return (IAsyncReader)OpenReader(new FileInfo(path), readerOptions);
|
||||
}
|
||||
|
||||
public static IAsyncReader OpenAsyncReader(
|
||||
Stream stream,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
public static IAsyncReader OpenAsyncReader(Stream stream, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IAsyncReader)OpenReader(stream, readerOptions);
|
||||
}
|
||||
|
||||
public static IAsyncReader OpenAsyncReader(
|
||||
FileInfo fileInfo,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
ReaderOptions? readerOptions = null
|
||||
)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IAsyncReader)OpenReader(fileInfo, readerOptions);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
|
||||
namespace SharpCompress.Readers.GZip;
|
||||
|
||||
@@ -8,34 +7,22 @@ public partial class GZipReader
|
||||
: IReaderOpenable
|
||||
#endif
|
||||
{
|
||||
public static IAsyncReader OpenAsyncReader(
|
||||
string path,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
public static IAsyncReader OpenAsyncReader(string path, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
path.NotNullOrEmpty(nameof(path));
|
||||
return (IAsyncReader)OpenReader(new FileInfo(path), readerOptions);
|
||||
}
|
||||
|
||||
public static IAsyncReader OpenAsyncReader(
|
||||
Stream stream,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
public static IAsyncReader OpenAsyncReader(Stream stream, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IAsyncReader)OpenReader(stream, readerOptions);
|
||||
}
|
||||
|
||||
public static IAsyncReader OpenAsyncReader(
|
||||
FileInfo fileInfo,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
ReaderOptions? readerOptions = null
|
||||
)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IAsyncReader)OpenReader(fileInfo, readerOptions);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,20 +17,17 @@ public interface IReaderOpenable
|
||||
|
||||
public static abstract IAsyncReader OpenAsyncReader(
|
||||
string path,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
ReaderOptions? readerOptions = null
|
||||
);
|
||||
|
||||
public static abstract IAsyncReader OpenAsyncReader(
|
||||
Stream stream,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
ReaderOptions? readerOptions = null
|
||||
);
|
||||
|
||||
public static abstract IAsyncReader OpenAsyncReader(
|
||||
FileInfo fileInfo,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
ReaderOptions? readerOptions = null
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
15
src/SharpCompress/Readers/Lzw/LzwReader.Async.cs
Normal file
15
src/SharpCompress/Readers/Lzw/LzwReader.Async.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Common.Lzw;
|
||||
|
||||
namespace SharpCompress.Readers.Lzw;
|
||||
|
||||
public partial class LzwReader
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns entries asynchronously for streams that only support async reads.
|
||||
/// </summary>
|
||||
protected override IAsyncEnumerable<LzwEntry> GetEntriesAsync(Stream stream) =>
|
||||
LzwEntry.GetEntriesAsync(stream, Options);
|
||||
}
|
||||
46
src/SharpCompress/Readers/Lzw/LzwReader.Factory.cs
Normal file
46
src/SharpCompress/Readers/Lzw/LzwReader.Factory.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using System.IO;
|
||||
|
||||
namespace SharpCompress.Readers.Lzw;
|
||||
|
||||
public partial class LzwReader
|
||||
#if NET8_0_OR_GREATER
|
||||
: IReaderOpenable
|
||||
#endif
|
||||
{
|
||||
public static IAsyncReader OpenAsyncReader(string path, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
path.NotNullOrEmpty(nameof(path));
|
||||
return (IAsyncReader)OpenReader(new FileInfo(path), readerOptions);
|
||||
}
|
||||
|
||||
public static IAsyncReader OpenAsyncReader(Stream stream, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
return (IAsyncReader)OpenReader(stream, readerOptions);
|
||||
}
|
||||
|
||||
public static IAsyncReader OpenAsyncReader(
|
||||
FileInfo fileInfo,
|
||||
ReaderOptions? readerOptions = null
|
||||
)
|
||||
{
|
||||
return (IAsyncReader)OpenReader(fileInfo, readerOptions);
|
||||
}
|
||||
|
||||
public static IReader OpenReader(string filePath, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
filePath.NotNullOrEmpty(nameof(filePath));
|
||||
return OpenReader(new FileInfo(filePath), readerOptions);
|
||||
}
|
||||
|
||||
public static IReader OpenReader(FileInfo fileInfo, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
fileInfo.NotNull(nameof(fileInfo));
|
||||
return OpenReader(fileInfo.OpenRead(), readerOptions);
|
||||
}
|
||||
|
||||
public static IReader OpenReader(Stream stream, ReaderOptions? options = null)
|
||||
{
|
||||
stream.NotNull(nameof(stream));
|
||||
return new LzwReader(stream, options ?? new ReaderOptions());
|
||||
}
|
||||
}
|
||||
19
src/SharpCompress/Readers/Lzw/LzwReader.cs
Normal file
19
src/SharpCompress/Readers/Lzw/LzwReader.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Common.Lzw;
|
||||
|
||||
namespace SharpCompress.Readers.Lzw;
|
||||
|
||||
public partial class LzwReader : AbstractReader<LzwEntry, LzwVolume>
|
||||
{
|
||||
private LzwReader(Stream stream, ReaderOptions options)
|
||||
: base(options, ArchiveType.Lzw) => Volume = new LzwVolume(stream, options, 0);
|
||||
|
||||
public override LzwVolume Volume { get; }
|
||||
|
||||
protected override IEnumerable<LzwEntry> GetEntries(Stream stream) =>
|
||||
LzwEntry.GetEntries(stream, Options);
|
||||
|
||||
// GetEntriesAsync moved to LzwReader.Async.cs
|
||||
}
|
||||
@@ -1,40 +1,27 @@
|
||||
#if NET8_0_OR_GREATER
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using SharpCompress.Common;
|
||||
|
||||
namespace SharpCompress.Readers.Rar;
|
||||
|
||||
public partial class RarReader : IReaderOpenable
|
||||
{
|
||||
public static IAsyncReader OpenAsyncReader(
|
||||
string path,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
public static IAsyncReader OpenAsyncReader(string path, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
path.NotNullOrEmpty(nameof(path));
|
||||
return (IAsyncReader)OpenReader(new FileInfo(path), readerOptions);
|
||||
}
|
||||
|
||||
public static IAsyncReader OpenAsyncReader(
|
||||
Stream stream,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
public static IAsyncReader OpenAsyncReader(Stream stream, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IAsyncReader)OpenReader(stream, readerOptions);
|
||||
}
|
||||
|
||||
public static IAsyncReader OpenAsyncReader(
|
||||
FileInfo fileInfo,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
ReaderOptions? readerOptions = null
|
||||
)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IAsyncReader)OpenReader(fileInfo, readerOptions);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ public static partial class ReaderFactory
|
||||
}
|
||||
|
||||
throw new InvalidFormatException(
|
||||
"Cannot determine compressed stream type. Supported Reader Formats: Ace, Arc, Arj, Zip, GZip, BZip2, Tar, Rar, LZip, XZ, ZStandard"
|
||||
"Cannot determine compressed stream type. Supported Reader Formats: Ace, Arc, Arj, Zip, GZip, BZip2, Tar, Rar, LZip, Lzw, XZ, ZStandard"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using SharpCompress.Common;
|
||||
|
||||
namespace SharpCompress.Readers.Tar;
|
||||
@@ -9,34 +8,22 @@ public partial class TarReader
|
||||
: IReaderOpenable
|
||||
#endif
|
||||
{
|
||||
public static IAsyncReader OpenAsyncReader(
|
||||
string path,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
public static IAsyncReader OpenAsyncReader(string path, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
path.NotNullOrEmpty(nameof(path));
|
||||
return (IAsyncReader)OpenReader(new FileInfo(path), readerOptions);
|
||||
}
|
||||
|
||||
public static IAsyncReader OpenAsyncReader(
|
||||
Stream stream,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
public static IAsyncReader OpenAsyncReader(Stream stream, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IAsyncReader)OpenReader(stream, readerOptions);
|
||||
}
|
||||
|
||||
public static IAsyncReader OpenAsyncReader(
|
||||
FileInfo fileInfo,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
ReaderOptions? readerOptions = null
|
||||
)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IAsyncReader)OpenReader(fileInfo, readerOptions);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,40 +1,27 @@
|
||||
#if NET8_0_OR_GREATER
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using SharpCompress.Common;
|
||||
|
||||
namespace SharpCompress.Readers.Zip;
|
||||
|
||||
public partial class ZipReader : IReaderOpenable
|
||||
{
|
||||
public static IAsyncReader OpenAsyncReader(
|
||||
string path,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
public static IAsyncReader OpenAsyncReader(string path, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
path.NotNullOrEmpty(nameof(path));
|
||||
return (IAsyncReader)OpenReader(new FileInfo(path), readerOptions);
|
||||
}
|
||||
|
||||
public static IAsyncReader OpenAsyncReader(
|
||||
Stream stream,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
public static IAsyncReader OpenAsyncReader(Stream stream, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IAsyncReader)OpenReader(stream, readerOptions);
|
||||
}
|
||||
|
||||
public static IAsyncReader OpenAsyncReader(
|
||||
FileInfo fileInfo,
|
||||
ReaderOptions? readerOptions = null,
|
||||
CancellationToken cancellationToken = default
|
||||
ReaderOptions? readerOptions = null
|
||||
)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IAsyncReader)OpenReader(fileInfo, readerOptions);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#if NET8_0_OR_GREATER
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using SharpCompress.Common;
|
||||
|
||||
namespace SharpCompress.Writers.GZip;
|
||||
@@ -25,33 +24,18 @@ public partial class GZipWriter : IWriterOpenable<GZipWriterOptions>
|
||||
return new GZipWriter(stream, writerOptions);
|
||||
}
|
||||
|
||||
public static IAsyncWriter OpenAsyncWriter(
|
||||
string path,
|
||||
GZipWriterOptions writerOptions,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
public static IAsyncWriter OpenAsyncWriter(string path, GZipWriterOptions writerOptions)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IAsyncWriter)OpenWriter(path, writerOptions);
|
||||
}
|
||||
|
||||
public static IAsyncWriter OpenAsyncWriter(
|
||||
Stream stream,
|
||||
GZipWriterOptions writerOptions,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
public static IAsyncWriter OpenAsyncWriter(Stream stream, GZipWriterOptions writerOptions)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IAsyncWriter)OpenWriter(stream, writerOptions);
|
||||
}
|
||||
|
||||
public static IAsyncWriter OpenAsyncWriter(
|
||||
FileInfo fileInfo,
|
||||
GZipWriterOptions writerOptions,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
public static IAsyncWriter OpenAsyncWriter(FileInfo fileInfo, GZipWriterOptions writerOptions)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IAsyncWriter)OpenWriter(fileInfo, writerOptions);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,24 +19,20 @@ public interface IWriterOpenable<TWriterOptions>
|
||||
/// <param name="stream">The stream to write to.</param>
|
||||
/// <param name="archiveType">The archive type.</param>
|
||||
/// <param name="writerOptions">Writer options.</param>
|
||||
/// <param name="cancellationToken">Cancellation token.</param>
|
||||
/// <returns>A task that returns an IWriter.</returns>
|
||||
public static abstract IAsyncWriter OpenAsyncWriter(
|
||||
Stream stream,
|
||||
TWriterOptions writerOptions,
|
||||
CancellationToken cancellationToken = default
|
||||
TWriterOptions writerOptions
|
||||
);
|
||||
|
||||
public static abstract IAsyncWriter OpenAsyncWriter(
|
||||
string filePath,
|
||||
TWriterOptions writerOptions,
|
||||
CancellationToken cancellationToken = default
|
||||
TWriterOptions writerOptions
|
||||
);
|
||||
|
||||
public static abstract IAsyncWriter OpenAsyncWriter(
|
||||
FileInfo fileInfo,
|
||||
TWriterOptions writerOptions,
|
||||
CancellationToken cancellationToken = default
|
||||
TWriterOptions writerOptions
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#if NET8_0_OR_GREATER
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using SharpCompress.Common;
|
||||
|
||||
namespace SharpCompress.Writers.Tar;
|
||||
@@ -25,33 +24,18 @@ public partial class TarWriter : IWriterOpenable<TarWriterOptions>
|
||||
return new TarWriter(stream, writerOptions);
|
||||
}
|
||||
|
||||
public static IAsyncWriter OpenAsyncWriter(
|
||||
string path,
|
||||
TarWriterOptions writerOptions,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
public static IAsyncWriter OpenAsyncWriter(string path, TarWriterOptions writerOptions)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IAsyncWriter)OpenWriter(path, writerOptions);
|
||||
}
|
||||
|
||||
public static IAsyncWriter OpenAsyncWriter(
|
||||
Stream stream,
|
||||
TarWriterOptions writerOptions,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
public static IAsyncWriter OpenAsyncWriter(Stream stream, TarWriterOptions writerOptions)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IAsyncWriter)OpenWriter(stream, writerOptions);
|
||||
}
|
||||
|
||||
public static IAsyncWriter OpenAsyncWriter(
|
||||
FileInfo fileInfo,
|
||||
TarWriterOptions writerOptions,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
public static IAsyncWriter OpenAsyncWriter(FileInfo fileInfo, TarWriterOptions writerOptions)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IAsyncWriter)OpenWriter(fileInfo, writerOptions);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#if NET8_0_OR_GREATER
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using SharpCompress.Common;
|
||||
|
||||
namespace SharpCompress.Writers.Zip;
|
||||
@@ -25,33 +24,18 @@ public partial class ZipWriter : IWriterOpenable<ZipWriterOptions>
|
||||
return new ZipWriter(stream, writerOptions);
|
||||
}
|
||||
|
||||
public static IAsyncWriter OpenAsyncWriter(
|
||||
string path,
|
||||
ZipWriterOptions writerOptions,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
public static IAsyncWriter OpenAsyncWriter(string path, ZipWriterOptions writerOptions)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IAsyncWriter)OpenWriter(path, writerOptions);
|
||||
}
|
||||
|
||||
public static IAsyncWriter OpenAsyncWriter(
|
||||
Stream stream,
|
||||
ZipWriterOptions writerOptions,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
public static IAsyncWriter OpenAsyncWriter(Stream stream, ZipWriterOptions writerOptions)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IAsyncWriter)OpenWriter(stream, writerOptions);
|
||||
}
|
||||
|
||||
public static IAsyncWriter OpenAsyncWriter(
|
||||
FileInfo fileInfo,
|
||||
ZipWriterOptions writerOptions,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
public static IAsyncWriter OpenAsyncWriter(FileInfo fileInfo, ZipWriterOptions writerOptions)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return (IAsyncWriter)OpenWriter(fileInfo, writerOptions);
|
||||
}
|
||||
}
|
||||
|
||||
43
tests/SharpCompress.Test/Lzw/LzwReaderAsyncTests.cs
Normal file
43
tests/SharpCompress.Test/Lzw/LzwReaderAsyncTests.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
using System.IO;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Readers;
|
||||
using SharpCompress.Readers.Lzw;
|
||||
using Xunit;
|
||||
|
||||
namespace SharpCompress.Test.Lzw;
|
||||
|
||||
public class LzwReaderAsyncTests : ReaderTests
|
||||
{
|
||||
public LzwReaderAsyncTests() => UseExtensionInsteadOfNameToVerify = true;
|
||||
|
||||
[Fact]
|
||||
public async System.Threading.Tasks.Task Lzw_Reader_Async()
|
||||
{
|
||||
await ReadAsync("Tar.tar.Z", CompressionType.Lzw);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async System.Threading.Tasks.Task Lzw_Reader_Plain_Z_File_Async()
|
||||
{
|
||||
// Test async reading of a plain .Z file (not tar-wrapped) using LzwReader directly
|
||||
using Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "large_test.txt.Z"));
|
||||
using var reader = LzwReader.OpenReader(stream);
|
||||
|
||||
Assert.Equal(ArchiveType.Lzw, reader.ArchiveType);
|
||||
Assert.True(reader.MoveToNextEntry());
|
||||
|
||||
var entry = reader.Entry;
|
||||
Assert.NotNull(entry);
|
||||
Assert.Equal(CompressionType.Lzw, entry.CompressionType);
|
||||
|
||||
// When opened as FileStream, key should be derived from filename
|
||||
Assert.Equal("large_test.txt", entry.Key);
|
||||
|
||||
// Decompress asynchronously
|
||||
using var entryStream = reader.OpenEntryStream();
|
||||
using var ms = new MemoryStream();
|
||||
await entryStream.CopyToAsync(ms);
|
||||
|
||||
Assert.Equal(22300, ms.Length);
|
||||
}
|
||||
}
|
||||
91
tests/SharpCompress.Test/Lzw/LzwReaderTests.cs
Normal file
91
tests/SharpCompress.Test/Lzw/LzwReaderTests.cs
Normal file
@@ -0,0 +1,91 @@
|
||||
using System.IO;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.IO;
|
||||
using SharpCompress.Readers;
|
||||
using SharpCompress.Readers.Lzw;
|
||||
using Xunit;
|
||||
|
||||
namespace SharpCompress.Test.Lzw;
|
||||
|
||||
public class LzwReaderTests : ReaderTests
|
||||
{
|
||||
public LzwReaderTests() => UseExtensionInsteadOfNameToVerify = true;
|
||||
|
||||
[Fact]
|
||||
public void Lzw_Reader_Generic() => Read("Tar.tar.Z", CompressionType.Lzw);
|
||||
|
||||
[Fact]
|
||||
public void Lzw_Reader_Generic2()
|
||||
{
|
||||
//read only as Lzw item
|
||||
using Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.Z"));
|
||||
using var reader = LzwReader.OpenReader(SharpCompressStream.CreateNonDisposing(stream));
|
||||
while (reader.MoveToNextEntry())
|
||||
{
|
||||
// LZW doesn't have CRC or Size in header like GZip, so we just check the entry exists
|
||||
Assert.NotNull(reader.Entry);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Lzw_Reader_Factory_Detects_Tar_Wrapper()
|
||||
{
|
||||
// Note: Testing with Tar.tar.Z because:
|
||||
// 1. LzwStream only supports decompression, not compression
|
||||
// 2. This tests the important tar wrapper detection code path in LzwFactory.TryOpenReader
|
||||
// 3. Verifies that tar.Z files correctly return TarReader with CompressionType.Lzw
|
||||
using Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.Z"));
|
||||
using var reader = ReaderFactory.OpenReader(
|
||||
stream,
|
||||
new ReaderOptions { LeaveStreamOpen = false }
|
||||
);
|
||||
|
||||
// Should detect as Tar archive with Lzw compression
|
||||
Assert.Equal(ArchiveType.Tar, reader.ArchiveType);
|
||||
Assert.True(reader.MoveToNextEntry());
|
||||
Assert.NotNull(reader.Entry);
|
||||
Assert.Equal(CompressionType.Lzw, reader.Entry.CompressionType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Lzw_Reader_Plain_Z_File()
|
||||
{
|
||||
// Test with a plain .Z file (not tar-wrapped) using LzwReader directly
|
||||
using Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "large_test.txt.Z"));
|
||||
using var reader = LzwReader.OpenReader(stream);
|
||||
|
||||
Assert.True(reader.MoveToNextEntry());
|
||||
var entry = reader.Entry;
|
||||
Assert.NotNull(entry);
|
||||
Assert.Equal(CompressionType.Lzw, entry.CompressionType);
|
||||
|
||||
// Entry key should be "large_test.txt" (stripped .Z extension) when opened via FileStream
|
||||
Assert.Equal("large_test.txt", entry.Key);
|
||||
|
||||
// Decompress and verify content
|
||||
using var entryStream = reader.OpenEntryStream();
|
||||
using var ms = new MemoryStream();
|
||||
entryStream.CopyTo(ms);
|
||||
var decompressed = System.Text.Encoding.UTF8.GetString(ms.ToArray());
|
||||
|
||||
Assert.Equal(22300, ms.Length);
|
||||
Assert.Contains("This is a test file for LZW compression testing", decompressed);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Lzw_Reader_Factory_Detects_Plain_Z_File()
|
||||
{
|
||||
// Test that ReaderFactory correctly identifies a plain .Z file (not tar-wrapped)
|
||||
using Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "large_test.txt.Z"));
|
||||
using var reader = ReaderFactory.OpenReader(stream);
|
||||
|
||||
// Should detect as Lzw archive (not Tar)
|
||||
Assert.Equal(ArchiveType.Lzw, reader.ArchiveType);
|
||||
Assert.True(reader.MoveToNextEntry());
|
||||
Assert.NotNull(reader.Entry);
|
||||
Assert.Equal(CompressionType.Lzw, reader.Entry.CompressionType);
|
||||
|
||||
// When opened via ReaderFactory with a non-FileStream, key defaults to "data"
|
||||
Assert.NotNull(reader.Entry.Key);
|
||||
}
|
||||
}
|
||||
@@ -178,8 +178,7 @@ public abstract class ReaderTests : TestBase
|
||||
await using (
|
||||
var reader = await ReaderFactory.OpenAsyncReader(
|
||||
new AsyncOnlyStream(testStream),
|
||||
options,
|
||||
cancellationToken
|
||||
options
|
||||
)
|
||||
)
|
||||
{
|
||||
|
||||
@@ -91,8 +91,7 @@ public class WriterTests : TestBase
|
||||
|
||||
await using var reader = await ReaderFactory.OpenAsyncReader(
|
||||
new AsyncOnlyStream(SharpCompressStream.CreateNonDisposing(stream)),
|
||||
readerOptions,
|
||||
cancellationToken
|
||||
readerOptions
|
||||
);
|
||||
await reader.WriteAllToDirectoryAsync(SCRATCH_FILES_PATH, cancellationToken);
|
||||
}
|
||||
|
||||
BIN
tests/TestArchives/Archives/large_test.txt.Z
Normal file
BIN
tests/TestArchives/Archives/large_test.txt.Z
Normal file
Binary file not shown.
Reference in New Issue
Block a user