mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-09-23 23:45:14 +00:00
Zip ZStandard Writing with tests. Level support.
This commit is contained in:
@@ -28,4 +28,5 @@ public enum CompressionType
|
||||
Squashed,
|
||||
Crushed,
|
||||
Distilled,
|
||||
ZStandard,
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ internal enum ZipCompressionMethod
|
||||
Deflate64 = 9,
|
||||
BZip2 = 12,
|
||||
LZMA = 14,
|
||||
ZStd = 93,
|
||||
ZStandard = 93,
|
||||
Xz = 95,
|
||||
PPMd = 98,
|
||||
WinzipAes = 0x63, //http://www.winzip.com/aes_info.htm
|
||||
|
||||
@@ -46,6 +46,7 @@ public class ZipEntry : Entry
|
||||
ZipCompressionMethod.Reduce3 => CompressionType.Reduce3,
|
||||
ZipCompressionMethod.Reduce4 => CompressionType.Reduce4,
|
||||
ZipCompressionMethod.Explode => CompressionType.Explode,
|
||||
ZipCompressionMethod.ZStandard => CompressionType.ZStandard,
|
||||
_ => CompressionType.Unknown,
|
||||
};
|
||||
|
||||
|
||||
@@ -152,7 +152,7 @@ internal abstract class ZipFilePart : FilePart
|
||||
{
|
||||
return new XZStream(stream);
|
||||
}
|
||||
case ZipCompressionMethod.ZStd:
|
||||
case ZipCompressionMethod.ZStandard:
|
||||
{
|
||||
return new DecompressionStream(stream);
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ public sealed class GZipWriter : AbstractWriter
|
||||
new GZipStream(
|
||||
destination,
|
||||
CompressionMode.Compress,
|
||||
options?.CompressionLevel ?? CompressionLevel.Default,
|
||||
(CompressionLevel)(options?.CompressionLevel ?? (int)CompressionLevel.Default),
|
||||
WriterOptions.ArchiveEncoding.GetEncoding()
|
||||
)
|
||||
);
|
||||
|
||||
@@ -1,24 +1,18 @@
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Compressors.Deflate;
|
||||
using D = SharpCompress.Compressors.Deflate;
|
||||
|
||||
namespace SharpCompress.Writers.GZip;
|
||||
|
||||
public class GZipWriterOptions : WriterOptions
|
||||
{
|
||||
public GZipWriterOptions()
|
||||
: base(CompressionType.GZip) { }
|
||||
: base(CompressionType.GZip, (int)(D.CompressionLevel.Default)) { }
|
||||
|
||||
internal GZipWriterOptions(WriterOptions options)
|
||||
: base(options.CompressionType)
|
||||
: base(options.CompressionType, (int)(D.CompressionLevel.Default))
|
||||
{
|
||||
LeaveStreamOpen = options.LeaveStreamOpen;
|
||||
ArchiveEncoding = options.ArchiveEncoding;
|
||||
|
||||
if (options is GZipWriterOptions writerOptions)
|
||||
{
|
||||
CompressionLevel = writerOptions.CompressionLevel;
|
||||
}
|
||||
CompressionLevel = options.CompressionLevel;
|
||||
}
|
||||
|
||||
public CompressionLevel CompressionLevel { get; set; } = CompressionLevel.Default;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,41 @@
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Common;
|
||||
using D = SharpCompress.Compressors.Deflate;
|
||||
|
||||
namespace SharpCompress.Writers;
|
||||
|
||||
public class WriterOptions : OptionsBase
|
||||
{
|
||||
public WriterOptions(CompressionType compressionType) => CompressionType = compressionType;
|
||||
public WriterOptions(CompressionType compressionType)
|
||||
{
|
||||
CompressionType = compressionType;
|
||||
CompressionLevel = compressionType switch
|
||||
{
|
||||
CompressionType.ZStandard => 3,
|
||||
CompressionType.Deflate => (int)D.CompressionLevel.Default,
|
||||
CompressionType.Deflate64 => (int)D.CompressionLevel.Default,
|
||||
CompressionType.GZip => (int)D.CompressionLevel.Default,
|
||||
_ => 0
|
||||
};
|
||||
}
|
||||
|
||||
public WriterOptions(CompressionType compressionType, int compressionLevel)
|
||||
{
|
||||
CompressionType = compressionType;
|
||||
CompressionLevel = compressionLevel;
|
||||
}
|
||||
|
||||
public CompressionType CompressionType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The compression level to be used when the compression type supports variable levels.
|
||||
/// Valid ranges depend on the compression algorithm:
|
||||
/// - Deflate/GZip: 0-9 (0=no compression, 6=default, 9=best compression)
|
||||
/// - ZStandard: 1-22 (1=fastest, 3=default, 22=best compression)
|
||||
/// Note: BZip2 and LZMA do not support compression levels in this implementation.
|
||||
/// Defaults are set automatically based on compression type in the constructor.
|
||||
/// </summary>
|
||||
public int CompressionLevel { get; set; }
|
||||
|
||||
public static implicit operator WriterOptions(CompressionType compressionType) =>
|
||||
new(compressionType);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace SharpCompress.Writers.Zip;
|
||||
public class ZipWriter : AbstractWriter
|
||||
{
|
||||
private readonly CompressionType compressionType;
|
||||
private readonly CompressionLevel compressionLevel;
|
||||
private readonly int compressionLevel;
|
||||
private readonly List<ZipCentralDirectoryEntry> entries = new();
|
||||
private readonly string zipComment;
|
||||
private long streamPosition;
|
||||
@@ -36,7 +36,7 @@ public class ZipWriter : AbstractWriter
|
||||
}
|
||||
|
||||
compressionType = zipWriterOptions.CompressionType;
|
||||
compressionLevel = zipWriterOptions.DeflateCompressionLevel;
|
||||
compressionLevel = zipWriterOptions.CompressionLevel;
|
||||
|
||||
if (WriterOptions.LeaveStreamOpen)
|
||||
{
|
||||
@@ -69,6 +69,7 @@ public class ZipWriter : AbstractWriter
|
||||
CompressionType.BZip2 => ZipCompressionMethod.BZip2,
|
||||
CompressionType.LZMA => ZipCompressionMethod.LZMA,
|
||||
CompressionType.PPMd => ZipCompressionMethod.PPMd,
|
||||
CompressionType.ZStandard => ZipCompressionMethod.ZStandard,
|
||||
_ => throw new InvalidFormatException("Invalid compression method: " + compressionType),
|
||||
};
|
||||
|
||||
@@ -117,7 +118,7 @@ public class ZipWriter : AbstractWriter
|
||||
OutputStream.NotNull(),
|
||||
entry,
|
||||
compression,
|
||||
options.DeflateCompressionLevel ?? compressionLevel
|
||||
options.CompressionLevel ?? compressionLevel
|
||||
);
|
||||
}
|
||||
|
||||
@@ -312,7 +313,7 @@ public class ZipWriter : AbstractWriter
|
||||
private readonly Stream writeStream;
|
||||
private readonly ZipWriter writer;
|
||||
private readonly ZipCompressionMethod zipCompressionMethod;
|
||||
private readonly CompressionLevel compressionLevel;
|
||||
private readonly int compressionLevel;
|
||||
private SharpCompressStream? counting;
|
||||
private ulong decompressed;
|
||||
|
||||
@@ -325,7 +326,7 @@ public class ZipWriter : AbstractWriter
|
||||
Stream originalStream,
|
||||
ZipCentralDirectoryEntry entry,
|
||||
ZipCompressionMethod zipCompressionMethod,
|
||||
CompressionLevel compressionLevel
|
||||
int compressionLevel
|
||||
)
|
||||
{
|
||||
this.writer = writer;
|
||||
@@ -363,7 +364,7 @@ public class ZipWriter : AbstractWriter
|
||||
}
|
||||
case ZipCompressionMethod.Deflate:
|
||||
{
|
||||
return new DeflateStream(counting, CompressionMode.Compress, compressionLevel);
|
||||
return new DeflateStream(counting, CompressionMode.Compress, (CompressionLevel)compressionLevel);
|
||||
}
|
||||
case ZipCompressionMethod.BZip2:
|
||||
{
|
||||
@@ -389,6 +390,10 @@ public class ZipWriter : AbstractWriter
|
||||
counting.Write(writer.PpmdProperties.Properties, 0, 2);
|
||||
return new PpmdStream(writer.PpmdProperties, counting, true);
|
||||
}
|
||||
case ZipCompressionMethod.ZStandard:
|
||||
{
|
||||
return new ZstdSharp.CompressionStream(counting, (int)writer.WriterOptions.CompressionLevel);
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw new NotSupportedException("CompressionMethod: " + zipCompressionMethod);
|
||||
|
||||
@@ -9,9 +9,29 @@ public class ZipWriterEntryOptions
|
||||
public CompressionType? CompressionType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// When CompressionType.Deflate is used, this property is referenced. Defaults to CompressionLevel.Default.
|
||||
/// The compression level to be used when the compression type supports variable levels.
|
||||
/// Valid ranges depend on the compression algorithm:
|
||||
/// - Deflate/GZip: 0-9 (0=no compression, 6=default, 9=best compression)
|
||||
/// - ZStandard: 1-22 (1=fastest, 3=default, 22=best compression)
|
||||
/// When null, uses the archive's default compression level for the specified compression type.
|
||||
/// Note: BZip2 and LZMA do not support compression levels in this implementation.
|
||||
/// </summary>
|
||||
public CompressionLevel? DeflateCompressionLevel { get; set; }
|
||||
public int? CompressionLevel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// When CompressionType.Deflate is used, this property is referenced.
|
||||
/// Valid range: 0-9 (0=no compression, 6=default, 9=best compression).
|
||||
/// When null, uses the archive's default compression level.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This property is deprecated. Use <see cref="CompressionLevel"/> instead.
|
||||
/// </remarks>
|
||||
[Obsolete("Use CompressionLevel property instead. This property will be removed in a future version.")]
|
||||
public CompressionLevel? DeflateCompressionLevel
|
||||
{
|
||||
get => CompressionLevel.HasValue ? (CompressionLevel)Math.Min(CompressionLevel.Value, 9) : null;
|
||||
set => CompressionLevel = value.HasValue ? (int)value.Value : null;
|
||||
}
|
||||
|
||||
public string? EntryComment { get; set; }
|
||||
|
||||
|
||||
@@ -1,31 +1,66 @@
|
||||
using System;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Compressors.Deflate;
|
||||
using D = SharpCompress.Compressors.Deflate;
|
||||
|
||||
namespace SharpCompress.Writers.Zip;
|
||||
|
||||
public class ZipWriterOptions : WriterOptions
|
||||
{
|
||||
public ZipWriterOptions(CompressionType compressionType)
|
||||
: base(compressionType) { }
|
||||
public ZipWriterOptions(CompressionType compressionType, CompressionLevel compressionLevel = D.CompressionLevel.Default)
|
||||
: base(compressionType, (int)compressionLevel) { }
|
||||
|
||||
internal ZipWriterOptions(WriterOptions options)
|
||||
: base(options.CompressionType)
|
||||
{
|
||||
LeaveStreamOpen = options.LeaveStreamOpen;
|
||||
ArchiveEncoding = options.ArchiveEncoding;
|
||||
CompressionLevel = options.CompressionLevel;
|
||||
|
||||
if (options is ZipWriterOptions writerOptions)
|
||||
{
|
||||
UseZip64 = writerOptions.UseZip64;
|
||||
DeflateCompressionLevel = writerOptions.DeflateCompressionLevel;
|
||||
ArchiveComment = writerOptions.ArchiveComment;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When CompressionType.Deflate is used, this property is referenced. Defaults to CompressionLevel.Default.
|
||||
/// Sets the compression level for Deflate compression (0-9).
|
||||
/// This is a convenience method that sets the CompressionLevel property for Deflate compression.
|
||||
/// </summary>
|
||||
public CompressionLevel DeflateCompressionLevel { get; set; } = CompressionLevel.Default;
|
||||
/// <param name="level">Deflate compression level (0=no compression, 6=default, 9=best compression)</param>
|
||||
public void SetDeflateCompressionLevel(CompressionLevel level)
|
||||
{
|
||||
CompressionLevel = (int)level;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the compression level for ZStandard compression (1-22).
|
||||
/// This is a convenience method that sets the CompressionLevel property for ZStandard compression.
|
||||
/// </summary>
|
||||
/// <param name="level">ZStandard compression level (1=fastest, 3=default, 22=best compression)</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">Thrown when level is not between 1 and 22</exception>
|
||||
public void SetZStandardCompressionLevel(int level)
|
||||
{
|
||||
if (level < 1 || level > 22)
|
||||
throw new ArgumentOutOfRangeException(nameof(level), "ZStandard compression level must be between 1 and 22");
|
||||
|
||||
CompressionLevel = level;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Legacy property for Deflate compression levels.
|
||||
/// Valid range: 0-9 (0=no compression, 6=default, 9=best compression).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This property is deprecated. Use <see cref="WriterOptions.CompressionLevel"/> or <see cref="SetDeflateCompressionLevel"/> instead.
|
||||
/// </remarks>
|
||||
[Obsolete("Use CompressionLevel property or SetDeflateCompressionLevel method instead. This property will be removed in a future version.")]
|
||||
public CompressionLevel DeflateCompressionLevel
|
||||
{
|
||||
get => (CompressionLevel)Math.Min(CompressionLevel, 9);
|
||||
set => CompressionLevel = (int)value;
|
||||
}
|
||||
|
||||
public string? ArchiveComment { get; set; }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user