mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-09-23 23:45:14 +00:00
Changes before error encountered
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
This commit is contained in:
43
src/SharpCompress/Common/CompressionProgress.cs
Normal file
43
src/SharpCompress/Common/CompressionProgress.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
namespace SharpCompress.Common;
|
||||
|
||||
/// <summary>
|
||||
/// Represents progress information for compression operations.
|
||||
/// </summary>
|
||||
public sealed class CompressionProgress
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CompressionProgress"/> class.
|
||||
/// </summary>
|
||||
/// <param name="entryPath">The path of the entry being compressed.</param>
|
||||
/// <param name="bytesRead">Number of bytes read from the source.</param>
|
||||
/// <param name="totalBytes">Total bytes to be read from the source, or null if unknown.</param>
|
||||
public CompressionProgress(string entryPath, long bytesRead, long? totalBytes)
|
||||
{
|
||||
EntryPath = entryPath;
|
||||
BytesRead = bytesRead;
|
||||
TotalBytes = totalBytes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path of the entry being compressed.
|
||||
/// </summary>
|
||||
public string EntryPath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of bytes read from the source so far.
|
||||
/// </summary>
|
||||
public long BytesRead { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the total number of bytes to be read from the source, or null if unknown.
|
||||
/// </summary>
|
||||
public long? TotalBytes { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the progress percentage (0-100), or null if total bytes is unknown.
|
||||
/// </summary>
|
||||
public double? PercentComplete =>
|
||||
TotalBytes.HasValue && TotalBytes.Value > 0
|
||||
? (double)BytesRead / TotalBytes.Value * 100
|
||||
: null;
|
||||
}
|
||||
119
src/SharpCompress/IO/ProgressReportingStream.cs
Normal file
119
src/SharpCompress/IO/ProgressReportingStream.cs
Normal file
@@ -0,0 +1,119 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using SharpCompress.Common;
|
||||
|
||||
namespace SharpCompress.IO;
|
||||
|
||||
/// <summary>
|
||||
/// A stream wrapper that reports progress as data is written.
|
||||
/// </summary>
|
||||
internal sealed class ProgressReportingStream : Stream
|
||||
{
|
||||
private readonly Stream _baseStream;
|
||||
private readonly IProgress<CompressionProgress> _progress;
|
||||
private readonly string _entryPath;
|
||||
private readonly long? _totalBytes;
|
||||
private long _bytesWritten;
|
||||
|
||||
public ProgressReportingStream(
|
||||
Stream baseStream,
|
||||
IProgress<CompressionProgress> progress,
|
||||
string entryPath,
|
||||
long? totalBytes
|
||||
)
|
||||
{
|
||||
_baseStream = baseStream;
|
||||
_progress = progress;
|
||||
_entryPath = entryPath;
|
||||
_totalBytes = totalBytes;
|
||||
}
|
||||
|
||||
public override bool CanRead => _baseStream.CanRead;
|
||||
|
||||
public override bool CanSeek => _baseStream.CanSeek;
|
||||
|
||||
public override bool CanWrite => _baseStream.CanWrite;
|
||||
|
||||
public override long Length => _baseStream.Length;
|
||||
|
||||
public override long Position
|
||||
{
|
||||
get => _baseStream.Position;
|
||||
set => _baseStream.Position = value;
|
||||
}
|
||||
|
||||
public override void Flush() => _baseStream.Flush();
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count) =>
|
||||
_baseStream.Read(buffer, offset, count);
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin) =>
|
||||
_baseStream.Seek(offset, origin);
|
||||
|
||||
public override void SetLength(long value) => _baseStream.SetLength(value);
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
_baseStream.Write(buffer, offset, count);
|
||||
_bytesWritten += count;
|
||||
ReportProgress();
|
||||
}
|
||||
|
||||
public override void Write(ReadOnlySpan<byte> buffer)
|
||||
{
|
||||
_baseStream.Write(buffer);
|
||||
_bytesWritten += buffer.Length;
|
||||
ReportProgress();
|
||||
}
|
||||
|
||||
public override async Task WriteAsync(
|
||||
byte[] buffer,
|
||||
int offset,
|
||||
int count,
|
||||
CancellationToken cancellationToken
|
||||
)
|
||||
{
|
||||
await _baseStream.WriteAsync(buffer, offset, count, cancellationToken).ConfigureAwait(false);
|
||||
_bytesWritten += count;
|
||||
ReportProgress();
|
||||
}
|
||||
|
||||
public override async ValueTask WriteAsync(
|
||||
ReadOnlyMemory<byte> buffer,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
await _baseStream.WriteAsync(buffer, cancellationToken).ConfigureAwait(false);
|
||||
_bytesWritten += buffer.Length;
|
||||
ReportProgress();
|
||||
}
|
||||
|
||||
public override void WriteByte(byte value)
|
||||
{
|
||||
_baseStream.WriteByte(value);
|
||||
_bytesWritten++;
|
||||
ReportProgress();
|
||||
}
|
||||
|
||||
private void ReportProgress()
|
||||
{
|
||||
_progress.Report(new CompressionProgress(_entryPath, _bytesWritten, _totalBytes));
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
_baseStream.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
public override async ValueTask DisposeAsync()
|
||||
{
|
||||
await _baseStream.DisposeAsync().ConfigureAwait(false);
|
||||
await base.DisposeAsync().ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.IO;
|
||||
|
||||
namespace SharpCompress.Writers;
|
||||
|
||||
@@ -22,6 +23,23 @@ public abstract class AbstractWriter(ArchiveType type, WriterOptions writerOptio
|
||||
|
||||
protected WriterOptions WriterOptions { get; } = writerOptions;
|
||||
|
||||
/// <summary>
|
||||
/// Wraps the source stream with a progress-reporting stream if progress reporting is enabled.
|
||||
/// </summary>
|
||||
/// <param name="source">The source stream to wrap.</param>
|
||||
/// <param name="entryPath">The path of the entry being written.</param>
|
||||
/// <returns>A stream that reports progress, or the original stream if progress is not enabled.</returns>
|
||||
protected Stream WrapWithProgress(Stream source, string entryPath)
|
||||
{
|
||||
if (WriterOptions.Progress is null)
|
||||
{
|
||||
return source;
|
||||
}
|
||||
|
||||
long? totalBytes = source.CanSeek ? source.Length : null;
|
||||
return new ProgressReportingStream(source, WriterOptions.Progress, entryPath, totalBytes);
|
||||
}
|
||||
|
||||
public abstract void Write(string filename, Stream source, DateTime? modificationTime);
|
||||
|
||||
public virtual async Task WriteAsync(
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using SharpCompress.Common;
|
||||
using D = SharpCompress.Compressors.Deflate;
|
||||
|
||||
@@ -36,6 +37,12 @@ public class WriterOptions : OptionsBase
|
||||
/// </summary>
|
||||
public int CompressionLevel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// An optional progress reporter for tracking compression operations.
|
||||
/// When set, progress updates will be reported as entries are written.
|
||||
/// </summary>
|
||||
public IProgress<CompressionProgress>? Progress { get; set; }
|
||||
|
||||
public static implicit operator WriterOptions(CompressionType compressionType) =>
|
||||
new(compressionType);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user