mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-02-15 05:26:01 +00:00
Compare commits
4 Commits
copilot/fi
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b7f41acd19 | ||
|
|
71d993fab1 | ||
|
|
4546a3acd2 | ||
|
|
a2a1b2e8fd |
25
docs/API.md
25
docs/API.md
@@ -485,6 +485,31 @@ using (var archive = ZipArchive.CreateArchive())
|
||||
}
|
||||
```
|
||||
|
||||
### Buffered Forward-Only Streams
|
||||
|
||||
`SharpCompressStream` can wrap streams with buffering for forward-only scenarios:
|
||||
|
||||
```csharp
|
||||
// Wrap a non-seekable stream with buffering
|
||||
using (var bufferedStream = new SharpCompressStream(rawStream))
|
||||
{
|
||||
// Provides ring buffer functionality for reading ahead
|
||||
// and seeking within buffered data
|
||||
using (var reader = ReaderFactory.OpenReader(bufferedStream))
|
||||
{
|
||||
while (reader.MoveToNextEntry())
|
||||
{
|
||||
reader.WriteEntryToDirectory(@"C:\output");
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Useful for:
|
||||
- Non-seekable streams (network streams, pipes)
|
||||
- Forward-only reading with limited look-ahead
|
||||
- Buffering unbuffered streams for better performance
|
||||
|
||||
### Extract Specific Files
|
||||
|
||||
```csharp
|
||||
|
||||
@@ -5,7 +5,7 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace SharpCompress.IO;
|
||||
|
||||
internal partial class SharpCompressStream
|
||||
public partial class SharpCompressStream
|
||||
{
|
||||
public override Task<int> ReadAsync(
|
||||
byte[] buffer,
|
||||
|
||||
@@ -4,7 +4,7 @@ using SharpCompress.Common;
|
||||
|
||||
namespace SharpCompress.IO;
|
||||
|
||||
internal partial class SharpCompressStream
|
||||
public partial class SharpCompressStream
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a SharpCompressStream that acts as a passthrough wrapper.
|
||||
|
||||
@@ -4,7 +4,19 @@ using SharpCompress.Common;
|
||||
|
||||
namespace SharpCompress.IO;
|
||||
|
||||
internal partial class SharpCompressStream : Stream, IStreamStack
|
||||
/// <summary>
|
||||
/// Stream wrapper that provides optional ring-buffered reading for non-seekable
|
||||
/// or forward-only streams, enabling limited backward seeking required by some
|
||||
/// decompressors and archive formats.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// In most cases, callers should obtain an instance via the static
|
||||
/// <c>SharpCompressStream.Create(...)</c> methods rather than constructing this
|
||||
/// class directly. The <c>Create</c> methods select an appropriate configuration
|
||||
/// (such as passthrough vs buffered mode and buffer size) for the underlying
|
||||
/// stream and usage scenario.
|
||||
/// </remarks>
|
||||
public partial class SharpCompressStream : Stream, IStreamStack
|
||||
{
|
||||
public virtual Stream BaseStream() => stream;
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using SharpCompress.Compressors.Xz;
|
||||
using SharpCompress.IO;
|
||||
using SharpCompress.Test.Mocks;
|
||||
using Xunit;
|
||||
|
||||
@@ -34,4 +35,24 @@ public class XzStreamAsyncTests : XzTestsBase
|
||||
var uncompressed = await sr.ReadToEndAsync().ConfigureAwait(false);
|
||||
Assert.Equal(OriginalIndexed, uncompressed);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async ValueTask CanReadNonSeekableStreamAsync()
|
||||
{
|
||||
var nonSeekable = new ForwardOnlyStream(new MemoryStream(Compressed));
|
||||
var xz = new XZStream(SharpCompressStream.Create(nonSeekable));
|
||||
using var sr = new StreamReader(new AsyncOnlyStream(xz));
|
||||
var uncompressed = await sr.ReadToEndAsync().ConfigureAwait(false);
|
||||
Assert.Equal(Original, uncompressed);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async ValueTask CanReadNonSeekableEmptyStreamAsync()
|
||||
{
|
||||
var nonSeekable = new ForwardOnlyStream(new MemoryStream(CompressedEmpty));
|
||||
var xz = new XZStream(SharpCompressStream.Create(nonSeekable));
|
||||
using var sr = new StreamReader(new AsyncOnlyStream(xz));
|
||||
var uncompressed = await sr.ReadToEndAsync().ConfigureAwait(false);
|
||||
Assert.Equal(OriginalEmpty, uncompressed);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System.IO;
|
||||
using SharpCompress.Compressors.Xz;
|
||||
using SharpCompress.IO;
|
||||
using SharpCompress.Test.Mocks;
|
||||
using Xunit;
|
||||
|
||||
namespace SharpCompress.Test.Xz;
|
||||
@@ -32,4 +34,24 @@ public class XzStreamTests : XzTestsBase
|
||||
var uncompressed = sr.ReadToEnd();
|
||||
Assert.Equal(OriginalIndexed, uncompressed);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanReadNonSeekableStream()
|
||||
{
|
||||
var nonSeekable = new ForwardOnlyStream(new MemoryStream(Compressed));
|
||||
var xz = new XZStream(SharpCompressStream.Create(nonSeekable));
|
||||
using var sr = new StreamReader(xz);
|
||||
var uncompressed = sr.ReadToEnd();
|
||||
Assert.Equal(Original, uncompressed);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanReadNonSeekableEmptyStream()
|
||||
{
|
||||
var nonSeekable = new ForwardOnlyStream(new MemoryStream(CompressedEmpty));
|
||||
var xz = new XZStream(SharpCompressStream.Create(nonSeekable));
|
||||
using var sr = new StreamReader(xz);
|
||||
var uncompressed = sr.ReadToEnd();
|
||||
Assert.Equal(OriginalEmpty, uncompressed);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user