Compare commits

..

24 Commits

Author SHA1 Message Date
copilot-swe-agent[bot]
4a6e5232ae Add opt-in multi-threading support with SupportsMultiThreadedExtraction flag
- Added IArchive.SupportsMultiThreadedExtraction property to indicate if multi-threading is supported
- Added ReaderOptions.EnableMultiThreadedExtraction option to opt-in to multi-threading
- Updated SeekableZipFilePart, TarFilePart, and SeekableFilePart to check the flag
- Added test to verify multi-threading flag behavior
- Multi-threading is now disabled by default for backward compatibility

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-18 16:27:59 +00:00
copilot-swe-agent[bot]
3e23a6e5a6 Add multi-threading support for file-based archives - sync test passing
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-18 16:09:54 +00:00
copilot-swe-agent[bot]
e0a43e9727 Initial plan 2026-01-18 15:56:08 +00:00
Adam Hathcock
f5d83c0e33 Merge pull request #1135 from adamhathcock/copilot/consolidate-compile-flags 2026-01-15 18:47:37 +00:00
copilot-swe-agent[bot]
d2cb792d91 Change NET6_0_OR_GREATER to NET8_0_OR_GREATER
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-15 18:31:06 +00:00
copilot-swe-agent[bot]
52fef492a5 Additional simplifications: Remove NETCF, fix NET60 typo, consolidate NETCOREAPP2_1 pattern
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-15 18:09:06 +00:00
copilot-swe-agent[bot]
a5300f3383 Replace NETFRAMEWORK and NETSTANDARD2_0 with LEGACY_DOTNET compile flag
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-15 18:05:14 +00:00
copilot-swe-agent[bot]
cab3e7d498 Initial analysis: Planning compile flags consolidation
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-01-15 17:55:37 +00:00
copilot-swe-agent[bot]
405dbb30cd Initial plan 2026-01-15 17:50:54 +00:00
Adam Hathcock
3e219fa9ec Merge pull request #1131 from adamhathcock/adam/async-again
More test fixes and some perf changes
2026-01-15 16:20:25 +00:00
Adam Hathcock
ec310c87de merge fixes and fmt 2026-01-15 15:20:52 +00:00
Adam Hathcock
c55a383112 Merge remote-tracking branch 'origin/master' into adam/async-again
# Conflicts:
#	tests/SharpCompress.Test/GZip/GZipReaderAsyncTests.cs
#	tests/SharpCompress.Test/Rar/RarArchiveAsyncTests.cs
#	tests/SharpCompress.Test/SevenZip/SevenZipArchiveAsyncTests.cs
#	tests/SharpCompress.Test/Tar/TarArchiveAsyncTests.cs
#	tests/SharpCompress.Test/Tar/TarReaderAsyncTests.cs
#	tests/SharpCompress.Test/Zip/Zip64AsyncTests.cs
#	tests/SharpCompress.Test/Zip/ZipMemoryArchiveWithCrcAsyncTests.cs
2026-01-15 15:18:05 +00:00
Adam Hathcock
227fec66ad more pooling 2026-01-15 15:16:11 +00:00
Adam Hathcock
38eec23e07 rar byte[] better 2026-01-15 15:16:04 +00:00
Adam Hathcock
437271c6a2 change byte[] to memory using pool 2026-01-15 15:15:57 +00:00
Adam Hathcock
81a2060c75 reduce memory usage on headers 2026-01-15 15:15:50 +00:00
Adam Hathcock
5e90cfd6c5 Merge pull request #1128 from adamhathcock/adam/async-interface
Change interfaces to be consistent for new Async paths (definitely breaks things)
2026-01-15 15:13:33 +00:00
Adam Hathcock
b41296194f more updates to docs 2026-01-15 13:29:57 +00:00
Adam Hathcock
bf7416753a update docs 2026-01-15 13:04:09 +00:00
Adam Hathcock
7fbd751d27 change tests to work 2026-01-15 13:00:05 +00:00
Adam Hathcock
85b28dfe68 more refactoring 2026-01-15 12:20:35 +00:00
Adam Hathcock
779fba5deb finish the open refactor? 2026-01-15 12:06:54 +00:00
Adam Hathcock
2756b1f6f8 more refactor 2026-01-15 11:55:56 +00:00
Adam Hathcock
7b76858ae1 refactoring naming again 2026-01-15 11:41:30 +00:00
161 changed files with 1878 additions and 1615 deletions

4
.gitignore vendored
View File

@@ -20,7 +20,3 @@ artifacts/
.DS_Store
*.snupkg
# BenchmarkDotNet artifacts
BenchmarkDotNet.Artifacts/
**/BenchmarkDotNet.Artifacts/

View File

@@ -1,6 +1,5 @@
<Project>
<ItemGroup>
<PackageVersion Include="BenchmarkDotNet" Version="0.14.0" />
<PackageVersion Include="Bullseye" Version="6.1.0" />
<PackageVersion Include="AwesomeAssertions" Version="9.3.0" />
<PackageVersion Include="Glob" Version="1.1.9" />

View File

@@ -8,17 +8,17 @@ Quick reference for commonly used SharpCompress APIs.
```csharp
// Auto-detect format
using (var reader = ReaderFactory.Open(stream))
using (var reader = ReaderFactory.OpenReader(stream))
{
// Works with Zip, Tar, GZip, Rar, 7Zip, etc.
}
// Specific format - Archive API
using (var archive = ZipArchive.Open("file.zip"))
using (var archive = TarArchive.Open("file.tar"))
using (var archive = RarArchive.Open("file.rar"))
using (var archive = SevenZipArchive.Open("file.7z"))
using (var archive = GZipArchive.Open("file.gz"))
using (var archive = ZipArchive.OpenArchive("file.zip"))
using (var archive = TarArchive.OpenArchive("file.tar"))
using (var archive = RarArchive.OpenArchive("file.rar"))
using (var archive = SevenZipArchive.OpenArchive("file.7z"))
using (var archive = GZipArchive.OpenArchive("file.gz"))
// With options
var options = new ReaderOptions
@@ -27,30 +27,30 @@ var options = new ReaderOptions
LeaveStreamOpen = true,
ArchiveEncoding = new ArchiveEncoding { Default = Encoding.GetEncoding(932) }
};
using (var archive = ZipArchive.Open("encrypted.zip", options))
using (var archive = ZipArchive.OpenArchive("encrypted.zip", options))
```
### Creating Archives
```csharp
// Writer Factory
using (var writer = WriterFactory.Open(stream, ArchiveType.Zip, CompressionType.Deflate))
using (var writer = WriterFactory.OpenWriter(stream, ArchiveType.Zip, CompressionType.Deflate))
{
// Write entries
}
// Specific writer
using (var archive = ZipArchive.Create())
using (var archive = TarArchive.Create())
using (var archive = GZipArchive.Create())
using (var archive = ZipArchive.CreateArchive())
using (var archive = TarArchive.CreateArchive())
using (var archive = GZipArchive.CreateArchive())
// With options
var options = new WriterOptions(CompressionType.Deflate)
{
var options = new WriterOptions(CompressionType.Deflate)
{
CompressionLevel = 9,
LeaveStreamOpen = false
};
using (var archive = ZipArchive.Create())
using (var archive = ZipArchive.CreateArchive())
{
archive.SaveTo("output.zip", options);
}
@@ -63,7 +63,7 @@ using (var archive = ZipArchive.Create())
### Reading/Extracting
```csharp
using (var archive = ZipArchive.Open("file.zip"))
using (var archive = ZipArchive.OpenArchive("file.zip"))
{
// Get all entries
IEnumerable<IArchiveEntry> entries = archive.Entries;
@@ -91,7 +91,7 @@ using (var archive = ZipArchive.Open("file.zip"))
}
// Async extraction (requires IAsyncArchive)
using (var asyncArchive = await ZipArchive.OpenAsync("file.zip"))
using (var asyncArchive = await ZipArchive.OpenAsyncArchive("file.zip"))
{
await asyncArchive.WriteToDirectoryAsync(
@"C:\output",
@@ -122,7 +122,7 @@ foreach (var entry in archive.Entries)
### Creating Archives
```csharp
using (var archive = ZipArchive.Create())
using (var archive = ZipArchive.CreateArchive())
{
// Add file
archive.AddEntry("file.txt", @"C:\source\file.txt");
@@ -151,7 +151,7 @@ using (var archive = ZipArchive.Create())
```csharp
using (var stream = File.OpenRead("file.zip"))
using (var reader = ReaderFactory.Open(stream))
using (var reader = ReaderFactory.OpenReader(stream))
{
while (reader.MoveToNextEntry())
{
@@ -172,9 +172,9 @@ using (var reader = ReaderFactory.Open(stream))
}
}
// Async variants (use OpenAsync to get IAsyncReader)
// Async variants (use OpenAsyncReader to get IAsyncReader)
using (var stream = File.OpenRead("file.zip"))
using (var reader = await ReaderFactory.OpenAsync(stream))
using (var reader = await ReaderFactory.OpenAsyncReader(stream))
{
while (await reader.MoveToNextEntryAsync())
{
@@ -201,7 +201,7 @@ using (var reader = await ReaderFactory.OpenAsync(stream))
```csharp
using (var stream = File.Create("output.zip"))
using (var writer = WriterFactory.Open(stream, ArchiveType.Zip, CompressionType.Deflate))
using (var writer = WriterFactory.OpenWriter(stream, ArchiveType.Zip, CompressionType.Deflate))
{
// Write single file
using (var fileStream = File.OpenRead("source.txt"))
@@ -239,7 +239,7 @@ var options = new ReaderOptions
Default = Encoding.GetEncoding(932)
}
};
using (var archive = ZipArchive.Open("file.zip", options))
using (var archive = ZipArchive.OpenArchive("file.zip", options))
{
// ...
}
@@ -290,8 +290,8 @@ ArchiveType.Ace
// For Tar archives with compression
// Use WriterFactory to create compressed tar archives
using (var writer = WriterFactory.Open(stream, ArchiveType.Tar, CompressionType.GZip)) // Tar.GZip
using (var writer = WriterFactory.Open(stream, ArchiveType.Tar, CompressionType.BZip2)) // Tar.BZip2
using (var writer = WriterFactory.OpenWriter(stream, ArchiveType.Tar, CompressionType.GZip)) // Tar.GZip
using (var writer = WriterFactory.OpenWriter(stream, ArchiveType.Tar, CompressionType.BZip2)) // Tar.BZip2
```
### Archive Types
@@ -349,7 +349,7 @@ var progress = new Progress<ProgressReport>(report =>
});
var options = new ReaderOptions { Progress = progress };
using (var archive = ZipArchive.Open("archive.zip", options))
using (var archive = ZipArchive.OpenArchive("archive.zip", options))
{
archive.WriteToDirectory(@"C:\output");
}
@@ -363,7 +363,7 @@ cts.CancelAfter(TimeSpan.FromMinutes(5));
try
{
using (var archive = await ZipArchive.OpenAsync("archive.zip"))
using (var archive = await ZipArchive.OpenAsyncArchive("archive.zip"))
{
await archive.WriteToDirectoryAsync(
@"C:\output",
@@ -381,23 +381,23 @@ catch (OperationCanceledException)
### Create with Custom Compression
```csharp
using (var archive = ZipArchive.Create())
using (var archive = ZipArchive.CreateArchive())
{
archive.AddAllFromDirectory(@"D:\source");
// Fastest
archive.SaveTo("fast.zip", new WriterOptions(CompressionType.Deflate)
{
CompressionLevel = 1
archive.SaveTo("fast.zip", new WriterOptions(CompressionType.Deflate)
{
CompressionLevel = 1
});
// Balanced (default)
archive.SaveTo("normal.zip", CompressionType.Deflate);
// Best compression
archive.SaveTo("best.zip", new WriterOptions(CompressionType.Deflate)
{
CompressionLevel = 9
archive.SaveTo("best.zip", new WriterOptions(CompressionType.Deflate)
{
CompressionLevel = 9
});
}
```
@@ -406,7 +406,7 @@ using (var archive = ZipArchive.Create())
```csharp
using (var outputStream = new MemoryStream())
using (var archive = ZipArchive.Create())
using (var archive = ZipArchive.CreateArchive())
{
// Add content from memory
using (var contentStream = new MemoryStream(Encoding.UTF8.GetBytes("Hello")))
@@ -425,7 +425,7 @@ using (var archive = ZipArchive.Create())
### Extract Specific Files
```csharp
using (var archive = ZipArchive.Open("archive.zip"))
using (var archive = ZipArchive.OpenArchive("archive.zip"))
{
var filesToExtract = new[] { "file1.txt", "file2.txt" };
@@ -439,7 +439,7 @@ using (var archive = ZipArchive.Open("archive.zip"))
### List Archive Contents
```csharp
using (var archive = ZipArchive.Open("archive.zip"))
using (var archive = ZipArchive.OpenArchive("archive.zip"))
{
foreach (var entry in archive.Entries)
{
@@ -459,7 +459,7 @@ using (var archive = ZipArchive.Open("archive.zip"))
```csharp
var stream = File.OpenRead("archive.zip");
var archive = ZipArchive.Open(stream);
var archive = ZipArchive.OpenArchive(stream);
archive.WriteToDirectory(@"C:\output");
// stream not disposed - leaked resource
```
@@ -468,7 +468,7 @@ archive.WriteToDirectory(@"C:\output");
```csharp
using (var stream = File.OpenRead("archive.zip"))
using (var archive = ZipArchive.Open(stream))
using (var archive = ZipArchive.OpenArchive(stream))
{
archive.WriteToDirectory(@"C:\output");
}
@@ -479,7 +479,7 @@ using (var archive = ZipArchive.Open(stream))
```csharp
// Loading entire archive then iterating
using (var archive = ZipArchive.Open("large.zip"))
using (var archive = ZipArchive.OpenArchive("large.zip"))
{
var entries = archive.Entries.ToList(); // Loads all in memory
foreach (var e in entries)
@@ -494,7 +494,7 @@ using (var archive = ZipArchive.Open("large.zip"))
```csharp
// Streaming iteration
using (var stream = File.OpenRead("large.zip"))
using (var reader = ReaderFactory.Open(stream))
using (var reader = ReaderFactory.OpenReader(stream))
{
while (reader.MoveToNextEntry())
{

View File

@@ -76,7 +76,7 @@ Factory classes for auto-detecting archive format and creating appropriate reade
- Format-specific: `ZipFactory.cs`, `TarFactory.cs`, `RarFactory.cs`, etc.
**How It Works:**
1. `ReaderFactory.Open(stream)` probes stream signatures
1. `ReaderFactory.OpenReader(stream)` probes stream signatures
2. Identifies format by magic bytes
3. Creates appropriate reader instance
4. Returns generic `IReader` interface
@@ -142,7 +142,7 @@ Stream wrappers and utilities.
**Example:**
```csharp
// User calls factory
using (var reader = ReaderFactory.Open(stream)) // Returns IReader
using (var reader = ReaderFactory.OpenReader(stream)) // Returns IReader
{
while (reader.MoveToNextEntry())
{
@@ -175,7 +175,7 @@ CompressionType.LZMA // LZMA
CompressionType.PPMd // PPMd
// Writer uses strategy pattern
var archive = ZipArchive.Create();
var archive = ZipArchive.CreateArchive();
archive.SaveTo("output.zip", CompressionType.Deflate); // Use Deflate
archive.SaveTo("output.bz2", CompressionType.BZip2); // Use BZip2
```
@@ -248,7 +248,7 @@ foreach (var entry in entries)
}
// Reader API - provides iterator
IReader reader = ReaderFactory.Open(stream);
IReader reader = ReaderFactory.OpenReader(stream);
while (reader.MoveToNextEntry())
{
// Forward-only iteration - one entry at a time
@@ -381,7 +381,7 @@ public class NewFormatArchive : AbstractArchive
private NewFormatHeader _header;
private List<NewFormatEntry> _entries;
public static NewFormatArchive Open(Stream stream)
public static NewFormatArchive OpenArchive(Stream stream)
{
var archive = new NewFormatArchive();
archive._header = NewFormatHeader.Read(stream);
@@ -442,8 +442,8 @@ public class NewFormatFactory : Factory, IArchiveFactory, IReaderFactory
public static NewFormatFactory Instance { get; } = new();
public IArchive CreateArchive(Stream stream)
=> NewFormatArchive.Open(stream);
public IArchive CreateArchive(Stream stream)
=> NewFormatArchive.OpenArchive(stream);
public IReader CreateReader(Stream stream, ReaderOptions options)
=> new NewFormatReader(stream) { Options = options };
@@ -481,7 +481,7 @@ public class NewFormatTests : TestBase
public void NewFormat_Extracts_Successfully()
{
var archivePath = Path.Combine(TEST_ARCHIVES_PATH, "archive.newformat");
using (var archive = NewFormatArchive.Open(archivePath))
using (var archive = NewFormatArchive.OpenArchive(archivePath))
{
archive.WriteToDirectory(SCRATCH_FILES_PATH);
// Assert extraction
@@ -561,7 +561,7 @@ public class CustomStream : Stream
```csharp
// Correct: Nested using blocks
using (var fileStream = File.OpenRead("archive.zip"))
using (var archive = ZipArchive.Open(fileStream))
using (var archive = ZipArchive.OpenArchive(fileStream))
{
archive.WriteToDirectory(@"C:\output");
}
@@ -570,7 +570,7 @@ using (var archive = ZipArchive.Open(fileStream))
// Correct: Using with options
var options = new ReaderOptions { LeaveStreamOpen = true };
var stream = File.OpenRead("archive.zip");
using (var archive = ZipArchive.Open(stream, options))
using (var archive = ZipArchive.OpenArchive(stream, options))
{
archive.WriteToDirectory(@"C:\output");
}
@@ -641,7 +641,7 @@ public void Archive_Extraction_Works()
var testArchive = Path.Combine(TEST_ARCHIVES_PATH, "test.zip");
// Act
using (var archive = ZipArchive.Open(testArchive))
using (var archive = ZipArchive.OpenArchive(testArchive))
{
archive.WriteToDirectory(SCRATCH_FILES_PATH);
}

View File

@@ -27,7 +27,7 @@ var options = new ReaderOptions
}
};
using (var archive = ZipArchive.Open("japanese.zip", options))
using (var archive = ZipArchive.OpenArchive("japanese.zip", options))
{
foreach (var entry in archive.Entries)
{
@@ -51,7 +51,7 @@ var options = new ReaderOptions
{
ArchiveEncoding = new ArchiveEncoding { Default = Encoding.GetEncoding(932) }
};
using (var archive = ZipArchive.Open("file.zip", options))
using (var archive = ZipArchive.OpenArchive("file.zip", options))
{
// Use archive with correct encoding
}
@@ -64,7 +64,7 @@ var options = new ReaderOptions
ArchiveEncoding = new ArchiveEncoding { Default = Encoding.GetEncoding(932) }
};
using (var stream = File.OpenRead("file.zip"))
using (var reader = ReaderFactory.Open(stream, options))
using (var reader = ReaderFactory.OpenReader(stream, options))
{
while (reader.MoveToNextEntry())
{
@@ -89,7 +89,7 @@ var options = new ReaderOptions
Default = Encoding.GetEncoding(932)
}
};
using (var archive = ZipArchive.Open("japanese.zip", options))
using (var archive = ZipArchive.OpenArchive("japanese.zip", options))
{
// Correctly decodes Japanese filenames
}
@@ -266,7 +266,7 @@ SharpCompress attempts to auto-detect encoding, but this isn't always reliable:
```csharp
// Auto-detection (default)
using (var archive = ZipArchive.Open("file.zip")) // Uses UTF8 by default
using (var archive = ZipArchive.OpenArchive("file.zip")) // Uses UTF8 by default
{
// May show corrupted characters if archive uses different encoding
}
@@ -276,7 +276,7 @@ var options = new ReaderOptions
{
ArchiveEncoding = new ArchiveEncoding { Default = Encoding.GetEncoding(932) }
};
using (var archive = ZipArchive.Open("file.zip", options))
using (var archive = ZipArchive.OpenArchive("file.zip", options))
{
// Correct characters displayed
}
@@ -324,7 +324,7 @@ var options = new ReaderOptions
}
};
using (var archive = ZipArchive.Open("mixed.zip", options))
using (var archive = ZipArchive.OpenArchive("mixed.zip", options))
{
foreach (var entry in archive.Entries)
{
@@ -388,7 +388,7 @@ var options = new ReaderOptions
}
};
using (var archive = ZipArchive.Open("japanese_files.zip", options))
using (var archive = ZipArchive.OpenArchive("japanese_files.zip", options))
{
archive.WriteToDirectory(@"C:\output", new ExtractionOptions
{
@@ -410,7 +410,7 @@ var options = new ReaderOptions
}
};
using (var archive = ZipArchive.Open("french_files.zip", options))
using (var archive = ZipArchive.OpenArchive("french_files.zip", options))
{
archive.WriteToDirectory(@"C:\output");
}
@@ -428,7 +428,7 @@ var options = new ReaderOptions
}
};
using (var archive = ZipArchive.Open("chinese_files.zip", options))
using (var archive = ZipArchive.OpenArchive("chinese_files.zip", options))
{
archive.WriteToDirectory(@"C:\output");
}
@@ -445,7 +445,7 @@ var options = new ReaderOptions
}
};
using (var archive = ZipArchive.Open("russian_files.zip", options))
using (var archive = ZipArchive.OpenArchive("russian_files.zip", options))
{
archive.WriteToDirectory(@"C:\output");
}
@@ -463,7 +463,7 @@ var options = new ReaderOptions
};
using (var stream = File.OpenRead("japanese.zip"))
using (var reader = ReaderFactory.Open(stream, options))
using (var reader = ReaderFactory.OpenReader(stream, options))
{
while (reader.MoveToNextEntry())
{
@@ -484,7 +484,7 @@ When creating archives, SharpCompress uses UTF8 by default (recommended):
```csharp
// Create with UTF8 (default, recommended)
using (var archive = ZipArchive.Create())
using (var archive = ZipArchive.CreateArchive())
{
archive.AddAllFromDirectory(@"D:\my_files");
archive.SaveTo("output.zip", CompressionType.Deflate);

View File

@@ -24,7 +24,7 @@ Choose the right API based on your use case:
// - You need random access to entries
// - Stream is seekable (file, MemoryStream)
using (var archive = ZipArchive.Open("archive.zip"))
using (var archive = ZipArchive.OpenArchive("archive.zip"))
{
// Random access - all entries available
var specific = archive.Entries.FirstOrDefault(e => e.Key == "file.txt");
@@ -51,7 +51,7 @@ using (var archive = ZipArchive.Open("archive.zip"))
// - Forward-only processing is acceptable
using (var stream = File.OpenRead("large.zip"))
using (var reader = ReaderFactory.Open(stream))
using (var reader = ReaderFactory.OpenReader(stream))
{
while (reader.MoveToNextEntry())
{
@@ -129,7 +129,7 @@ For processing archives from downloads or pipes:
```csharp
// Download stream (non-seekable)
using (var httpStream = await httpClient.GetStreamAsync(url))
using (var reader = ReaderFactory.Open(httpStream))
using (var reader = ReaderFactory.OpenReader(httpStream))
{
// Process entries as they arrive
while (reader.MoveToNextEntry())
@@ -159,14 +159,14 @@ Choose based on your constraints:
```csharp
// Download then extract (requires disk space)
var archivePath = await DownloadFile(url, @"C:\temp\archive.zip");
using (var archive = ZipArchive.Open(archivePath))
using (var archive = ZipArchive.OpenArchive(archivePath))
{
archive.WriteToDirectory(@"C:\output");
}
// Stream during download (on-the-fly extraction)
using (var httpStream = await httpClient.GetStreamAsync(url))
using (var reader = ReaderFactory.Open(httpStream))
using (var reader = ReaderFactory.OpenReader(httpStream))
{
while (reader.MoveToNextEntry())
{
@@ -198,7 +198,7 @@ Extracting File3 requires decompressing File1 and File2 first.
**Random Extraction (Slow):**
```csharp
using (var archive = RarArchive.Open("solid.rar"))
using (var archive = RarArchive.OpenArchive("solid.rar"))
{
foreach (var entry in archive.Entries)
{
@@ -210,7 +210,7 @@ using (var archive = RarArchive.Open("solid.rar"))
**Sequential Extraction (Fast):**
```csharp
using (var archive = RarArchive.Open("solid.rar"))
using (var archive = RarArchive.OpenArchive("solid.rar"))
{
// Method 1: Use WriteToDirectory (recommended)
archive.WriteToDirectory(@"C:\output", new ExtractionOptions
@@ -256,7 +256,7 @@ using (var archive = RarArchive.Open("solid.rar"))
// Level 9 = Slowest, best compression
// Write with different compression levels
using (var archive = ZipArchive.Create())
using (var archive = ZipArchive.CreateArchive())
{
archive.AddAllFromDirectory(@"D:\data");
@@ -293,7 +293,7 @@ using (var archive = ZipArchive.Create())
// Smaller block size = lower memory, faster
// Larger block size = better compression, slower
using (var archive = TarArchive.Create())
using (var archive = TarArchive.CreateArchive())
{
archive.AddAllFromDirectory(@"D:\data");
@@ -313,7 +313,7 @@ LZMA compression is very powerful but memory-intensive:
// - Better compression: larger dictionary
// Preset via CompressionType
using (var archive = TarArchive.Create())
using (var archive = TarArchive.CreateArchive())
{
archive.AddAllFromDirectory(@"D:\data");
archive.SaveTo("archive.tar.xz", CompressionType.LZMA); // Default settings
@@ -333,7 +333,7 @@ Async is beneficial when:
```csharp
// Async extraction (non-blocking)
using (var archive = ZipArchive.Open("archive.zip"))
using (var archive = ZipArchive.OpenArchive("archive.zip"))
{
await archive.WriteToDirectoryAsync(
@"C:\output",
@@ -353,7 +353,7 @@ Async doesn't improve performance for:
```csharp
// Sync extraction (simpler, same performance on fast I/O)
using (var archive = ZipArchive.Open("archive.zip"))
using (var archive = ZipArchive.OpenArchive("archive.zip"))
{
archive.WriteToDirectory(
@"C:\output",
@@ -373,7 +373,7 @@ cts.CancelAfter(TimeSpan.FromMinutes(5));
try
{
using (var archive = ZipArchive.Open("archive.zip"))
using (var archive = ZipArchive.OpenArchive("archive.zip"))
{
await archive.WriteToDirectoryAsync(
@"C:\output",
@@ -408,14 +408,14 @@ catch (OperationCanceledException)
// ✗ Slow - opens each archive separately
foreach (var file in files)
{
using (var archive = ZipArchive.Open("archive.zip"))
using (var archive = ZipArchive.OpenArchive("archive.zip"))
{
archive.WriteToDirectory(@"C:\output");
}
}
// ✓ Better - process multiple entries at once
using (var archive = ZipArchive.Open("archive.zip"))
using (var archive = ZipArchive.OpenArchive("archive.zip"))
{
archive.WriteToDirectory(@"C:\output");
}
@@ -425,7 +425,7 @@ using (var archive = ZipArchive.Open("archive.zip"))
```csharp
var sw = Stopwatch.StartNew();
using (var archive = ZipArchive.Open("large.zip"))
using (var archive = ZipArchive.OpenArchive("large.zip"))
{
archive.WriteToDirectory(@"C:\output");
}

View File

@@ -48,7 +48,7 @@ Also, look over the tests for more thorough [examples](https://github.com/adamha
### Create Zip Archive from multiple files
```C#
using(var archive = ZipArchive.Create())
using(var archive = ZipArchive.CreateArchive())
{
archive.AddEntry("file01.txt", "C:\\file01.txt");
archive.AddEntry("file02.txt", "C:\\file02.txt");
@@ -61,7 +61,7 @@ using(var archive = ZipArchive.Create())
### Create Zip Archive from all files in a directory to a file
```C#
using (var archive = ZipArchive.Create())
using (var archive = ZipArchive.CreateArchive())
{
archive.AddAllFromDirectory("D:\\temp");
archive.SaveTo("C:\\temp.zip", CompressionType.Deflate);
@@ -72,7 +72,7 @@ using (var archive = ZipArchive.Create())
```C#
var memoryStream = new MemoryStream();
using (var archive = ZipArchive.Create())
using (var archive = ZipArchive.CreateArchive())
{
archive.AddAllFromDirectory("D:\\temp");
archive.SaveTo(memoryStream, new WriterOptions(CompressionType.Deflate)
@@ -90,7 +90,7 @@ Note: Extracting a solid rar or 7z file needs to be done in sequential order to
`ExtractAllEntries` is primarily intended for solid archives (like solid Rar) or 7Zip archives, where sequential extraction provides the best performance. For general/simple extraction with any supported archive type, use `archive.WriteToDirectory()` instead.
```C#
using (var archive = RarArchive.Open("Test.rar"))
using (var archive = RarArchive.OpenArchive("Test.rar"))
{
// Simple extraction with RarArchive; this WriteToDirectory pattern works for all archive types
archive.WriteToDirectory(@"D:\temp", new ExtractionOptions()
@@ -104,7 +104,7 @@ using (var archive = RarArchive.Open("Test.rar"))
### Iterate over all files from a Rar file using RarArchive
```C#
using (var archive = RarArchive.Open("Test.rar"))
using (var archive = RarArchive.OpenArchive("Test.rar"))
{
foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory))
{
@@ -126,7 +126,7 @@ var progress = new Progress<ProgressReport>(report =>
Console.WriteLine($"Extracting {report.EntryPath}: {report.PercentComplete}%");
});
using (var archive = RarArchive.Open("archive.rar", new ReaderOptions { Progress = progress })) // Must be solid Rar or 7Zip
using (var archive = RarArchive.OpenArchive("archive.rar", new ReaderOptions { Progress = progress })) // Must be solid Rar or 7Zip
{
archive.WriteToDirectory(@"D:\output", new ExtractionOptions()
{
@@ -140,7 +140,7 @@ using (var archive = RarArchive.Open("archive.rar", new ReaderOptions { Progress
```C#
using (Stream stream = File.OpenRead("Tar.tar.bz2"))
using (var reader = ReaderFactory.Open(stream))
using (var reader = ReaderFactory.OpenReader(stream))
{
while (reader.MoveToNextEntry())
{
@@ -161,7 +161,7 @@ using (var reader = ReaderFactory.Open(stream))
```C#
using (Stream stream = File.OpenRead("Tar.tar.bz2"))
using (var reader = ReaderFactory.Open(stream))
using (var reader = ReaderFactory.OpenReader(stream))
{
while (reader.MoveToNextEntry())
{
@@ -180,7 +180,7 @@ using (var reader = ReaderFactory.Open(stream))
```C#
using (Stream stream = File.OpenWrite("C:\\temp.tgz"))
using (var writer = WriterFactory.Open(stream, ArchiveType.Tar, new WriterOptions(CompressionType.GZip)
using (var writer = WriterFactory.OpenWriter(stream, ArchiveType.Tar, new WriterOptions(CompressionType.GZip)
{
LeaveOpenStream = true
}))
@@ -199,7 +199,7 @@ opts.ArchiveEncoding.CustomDecoder = (data, x, y) =>
{
return encoding.GetString(data);
};
var tr = SharpCompress.Archives.Zip.ZipArchive.Open("test.zip", opts);
var tr = SharpCompress.Archives.Zip.ZipArchive.OpenArchive("test.zip", opts);
foreach(var entry in tr.Entries)
{
Console.WriteLine($"{entry.Key}");
@@ -213,7 +213,7 @@ foreach(var entry in tr.Entries)
**Extract single entry asynchronously:**
```C#
using (Stream stream = File.OpenRead("archive.zip"))
using (var reader = ReaderFactory.Open(stream))
using (var reader = ReaderFactory.OpenReader(stream))
{
while (reader.MoveToNextEntry())
{
@@ -234,7 +234,7 @@ using (var reader = ReaderFactory.Open(stream))
**Extract all entries asynchronously:**
```C#
using (Stream stream = File.OpenRead("archive.tar.gz"))
using (var reader = ReaderFactory.Open(stream))
using (var reader = ReaderFactory.OpenReader(stream))
{
await reader.WriteAllToDirectoryAsync(
@"D:\temp",
@@ -250,7 +250,7 @@ using (var reader = ReaderFactory.Open(stream))
**Open and process entry stream asynchronously:**
```C#
using (var archive = ZipArchive.Open("archive.zip"))
using (var archive = ZipArchive.OpenArchive("archive.zip"))
{
foreach (var entry in archive.Entries.Where(e => !e.IsDirectory))
{
@@ -268,7 +268,7 @@ using (var archive = ZipArchive.Open("archive.zip"))
**Write single file asynchronously:**
```C#
using (Stream archiveStream = File.OpenWrite("output.zip"))
using (var writer = WriterFactory.Open(archiveStream, ArchiveType.Zip, CompressionType.Deflate))
using (var writer = WriterFactory.OpenWriter(archiveStream, ArchiveType.Zip, CompressionType.Deflate))
{
using (Stream fileStream = File.OpenRead("input.txt"))
{
@@ -280,7 +280,7 @@ using (var writer = WriterFactory.Open(archiveStream, ArchiveType.Zip, Compressi
**Write entire directory asynchronously:**
```C#
using (Stream stream = File.OpenWrite("backup.tar.gz"))
using (var writer = WriterFactory.Open(stream, ArchiveType.Tar, new WriterOptions(CompressionType.GZip)))
using (var writer = WriterFactory.OpenWriter(stream, ArchiveType.Tar, new WriterOptions(CompressionType.GZip)))
{
await writer.WriteAllAsync(
@"D:\files",
@@ -299,7 +299,7 @@ var cts = new CancellationTokenSource();
cts.CancelAfter(TimeSpan.FromMinutes(5));
using (Stream stream = File.OpenWrite("archive.zip"))
using (var writer = WriterFactory.Open(stream, ArchiveType.Zip, CompressionType.Deflate))
using (var writer = WriterFactory.OpenWriter(stream, ArchiveType.Zip, CompressionType.Deflate))
{
try
{
@@ -316,7 +316,7 @@ using (var writer = WriterFactory.Open(stream, ArchiveType.Zip, CompressionType.
**Extract from archive asynchronously:**
```C#
using (var archive = ZipArchive.Open("archive.zip"))
using (var archive = ZipArchive.OpenArchive("archive.zip"))
{
// Simple async extraction - works for all archive types
await archive.WriteToDirectoryAsync(

View File

@@ -1,7 +1,7 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
#if !NETSTANDARD2_0 && !NETSTANDARD2_1 && !NETFRAMEWORK
#if !LEGACY_DOTNET
#define SUPPORTS_RUNTIME_INTRINSICS
#define SUPPORTS_HOTPATH
#endif

View File

@@ -145,6 +145,19 @@ public abstract class AbstractArchive<TEntry, TVolume> : IArchive, IAsyncArchive
/// </summary>
public virtual bool IsEncrypted => false;
/// <summary>
/// Returns whether multi-threaded extraction is supported for this archive.
/// Multi-threading is supported when:
/// 1. The archive is opened from a FileInfo or file path (not a stream)
/// 2. Multi-threading is explicitly enabled in ReaderOptions
/// 3. The archive is not SOLID (SOLID archives should use sequential extraction)
/// </summary>
public virtual bool SupportsMultiThreadedExtraction =>
_sourceStream is not null
&& _sourceStream.IsFileMode
&& ReaderOptions.EnableMultiThreadedExtraction
&& !IsSolid;
/// <summary>
/// The archive can find all the parts of the archive needed to fully extract the archive. This forces the parsing of the entire archive.
/// </summary>

View File

@@ -13,14 +13,14 @@ namespace SharpCompress.Archives;
public static class ArchiveFactory
{
public static IArchive Open(Stream stream, ReaderOptions? readerOptions = null)
public static IArchive OpenArchive(Stream stream, ReaderOptions? readerOptions = null)
{
readerOptions ??= new ReaderOptions();
stream = SharpCompressStream.Create(stream, bufferSize: readerOptions.BufferSize);
return FindFactory<IArchiveFactory>(stream).Open(stream, readerOptions);
return FindFactory<IArchiveFactory>(stream).OpenArchive(stream, readerOptions);
}
public static async ValueTask<IAsyncArchive> OpenAsync(
public static async ValueTask<IAsyncArchive> OpenAsyncArchive(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
@@ -29,10 +29,10 @@ public static class ArchiveFactory
readerOptions ??= new ReaderOptions();
stream = SharpCompressStream.Create(stream, bufferSize: readerOptions.BufferSize);
var factory = await FindFactoryAsync<IArchiveFactory>(stream, cancellationToken);
return factory.OpenAsync(stream, readerOptions);
return factory.OpenAsyncArchive(stream, readerOptions);
}
public static IWritableArchive Create(ArchiveType type)
public static IWritableArchive CreateArchive(ArchiveType type)
{
var factory = Factory
.Factories.OfType<IWriteableArchiveFactory>()
@@ -40,36 +40,36 @@ public static class ArchiveFactory
if (factory != null)
{
return factory.CreateWriteableArchive();
return factory.CreateArchive();
}
throw new NotSupportedException("Cannot create Archives of type: " + type);
}
public static IArchive Open(string filePath, ReaderOptions? options = null)
public static IArchive OpenArchive(string filePath, ReaderOptions? options = null)
{
filePath.NotNullOrEmpty(nameof(filePath));
return Open(new FileInfo(filePath), options);
return OpenArchive(new FileInfo(filePath), options);
}
public static ValueTask<IAsyncArchive> OpenAsync(
public static ValueTask<IAsyncArchive> OpenAsyncArchive(
string filePath,
ReaderOptions? options = null,
CancellationToken cancellationToken = default
)
{
filePath.NotNullOrEmpty(nameof(filePath));
return OpenAsync(new FileInfo(filePath), options, cancellationToken);
return OpenAsyncArchive(new FileInfo(filePath), options, cancellationToken);
}
public static IArchive Open(FileInfo fileInfo, ReaderOptions? options = null)
public static IArchive OpenArchive(FileInfo fileInfo, ReaderOptions? options = null)
{
options ??= new ReaderOptions { LeaveStreamOpen = false };
return FindFactory<IArchiveFactory>(fileInfo).Open(fileInfo, options);
return FindFactory<IArchiveFactory>(fileInfo).OpenArchive(fileInfo, options);
}
public static async ValueTask<IAsyncArchive> OpenAsync(
public static async ValueTask<IAsyncArchive> OpenAsyncArchive(
FileInfo fileInfo,
ReaderOptions? options = null,
CancellationToken cancellationToken = default
@@ -78,10 +78,13 @@ public static class ArchiveFactory
options ??= new ReaderOptions { LeaveStreamOpen = false };
var factory = await FindFactoryAsync<IArchiveFactory>(fileInfo, cancellationToken);
return factory.OpenAsync(fileInfo, options, cancellationToken);
return factory.OpenAsyncArchive(fileInfo, options, cancellationToken);
}
public static IArchive Open(IEnumerable<FileInfo> fileInfos, ReaderOptions? options = null)
public static IArchive OpenArchive(
IEnumerable<FileInfo> fileInfos,
ReaderOptions? options = null
)
{
fileInfos.NotNull(nameof(fileInfos));
var filesArray = fileInfos.ToArray();
@@ -93,16 +96,16 @@ public static class ArchiveFactory
var fileInfo = filesArray[0];
if (filesArray.Length == 1)
{
return Open(fileInfo, options);
return OpenArchive(fileInfo, options);
}
fileInfo.NotNull(nameof(fileInfo));
options ??= new ReaderOptions { LeaveStreamOpen = false };
return FindFactory<IMultiArchiveFactory>(fileInfo).Open(filesArray, options);
return FindFactory<IMultiArchiveFactory>(fileInfo).OpenArchive(filesArray, options);
}
public static async ValueTask<IAsyncArchive> OpenAsync(
public static async ValueTask<IAsyncArchive> OpenAsyncArchive(
IEnumerable<FileInfo> fileInfos,
ReaderOptions? options = null,
CancellationToken cancellationToken = default
@@ -118,17 +121,17 @@ public static class ArchiveFactory
var fileInfo = filesArray[0];
if (filesArray.Length == 1)
{
return await OpenAsync(fileInfo, options, cancellationToken);
return await OpenAsyncArchive(fileInfo, options, cancellationToken);
}
fileInfo.NotNull(nameof(fileInfo));
options ??= new ReaderOptions { LeaveStreamOpen = false };
var factory = await FindFactoryAsync<IMultiArchiveFactory>(fileInfo, cancellationToken);
return factory.OpenAsync(filesArray, options, cancellationToken);
return factory.OpenAsyncArchive(filesArray, options, cancellationToken);
}
public static IArchive Open(IEnumerable<Stream> streams, ReaderOptions? options = null)
public static IArchive OpenArchive(IEnumerable<Stream> streams, ReaderOptions? options = null)
{
streams.NotNull(nameof(streams));
var streamsArray = streams.ToArray();
@@ -140,16 +143,16 @@ public static class ArchiveFactory
var firstStream = streamsArray[0];
if (streamsArray.Length == 1)
{
return Open(firstStream, options);
return OpenArchive(firstStream, options);
}
firstStream.NotNull(nameof(firstStream));
options ??= new ReaderOptions();
return FindFactory<IMultiArchiveFactory>(firstStream).Open(streamsArray, options);
return FindFactory<IMultiArchiveFactory>(firstStream).OpenArchive(streamsArray, options);
}
public static async ValueTask<IAsyncArchive> OpenAsync(
public static async ValueTask<IAsyncArchive> OpenAsyncArchive(
IEnumerable<Stream> streams,
ReaderOptions? options = null,
CancellationToken cancellationToken = default
@@ -166,14 +169,14 @@ public static class ArchiveFactory
var firstStream = streamsArray[0];
if (streamsArray.Length == 1)
{
return await OpenAsync(firstStream, options, cancellationToken);
return await OpenAsyncArchive(firstStream, options, cancellationToken);
}
firstStream.NotNull(nameof(firstStream));
options ??= new ReaderOptions();
var factory = FindFactory<IMultiArchiveFactory>(firstStream);
return factory.OpenAsync(streamsArray, options);
return factory.OpenAsyncArchive(streamsArray, options);
}
public static void WriteToDirectory(
@@ -182,7 +185,7 @@ public static class ArchiveFactory
ExtractionOptions? options = null
)
{
using var archive = Open(sourceArchive);
using var archive = OpenArchive(sourceArchive);
archive.WriteToDirectory(destinationDirectory, options);
}

View File

@@ -31,22 +31,22 @@ internal class AutoArchiveFactory : IArchiveFactory
public FileInfo? GetFilePart(int index, FileInfo part1) => throw new NotSupportedException();
public IArchive Open(Stream stream, ReaderOptions? readerOptions = null) =>
ArchiveFactory.Open(stream, readerOptions);
public IArchive OpenArchive(Stream stream, ReaderOptions? readerOptions = null) =>
ArchiveFactory.OpenArchive(stream, readerOptions);
public IAsyncArchive OpenAsync(Stream stream, ReaderOptions? readerOptions = null) =>
(IAsyncArchive)Open(stream, readerOptions);
public IAsyncArchive OpenAsyncArchive(Stream stream, ReaderOptions? readerOptions = null) =>
(IAsyncArchive)OpenArchive(stream, readerOptions);
public IArchive Open(FileInfo fileInfo, ReaderOptions? readerOptions = null) =>
ArchiveFactory.Open(fileInfo, readerOptions);
public IArchive OpenArchive(FileInfo fileInfo, ReaderOptions? readerOptions = null) =>
ArchiveFactory.OpenArchive(fileInfo, readerOptions);
public IAsyncArchive OpenAsync(
public IAsyncArchive OpenAsyncArchive(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncArchive)Open(fileInfo, readerOptions);
return (IAsyncArchive)OpenArchive(fileInfo, readerOptions);
}
}

View File

@@ -16,11 +16,11 @@ namespace SharpCompress.Archives.GZip;
public partial class GZipArchive
#if NET8_0_OR_GREATER
: IArchiveOpenable<IWritableArchive, IWritableAsyncArchive>,
: IWritableArchiveOpenable,
IMultiArchiveOpenable<IWritableArchive, IWritableAsyncArchive>
#endif
{
public static IWritableAsyncArchive OpenAsync(
public static IWritableAsyncArchive OpenAsyncArchive(
string path,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
@@ -28,19 +28,22 @@ public partial class GZipArchive
{
cancellationToken.ThrowIfCancellationRequested();
path.NotNullOrEmpty(nameof(path));
return (IWritableAsyncArchive)Open(
return (IWritableAsyncArchive)OpenArchive(
new FileInfo(path),
readerOptions ?? new ReaderOptions()
);
}
public static IWritableArchive Open(string filePath, ReaderOptions? readerOptions = null)
public static IWritableArchive OpenArchive(string filePath, ReaderOptions? readerOptions = null)
{
filePath.NotNullOrEmpty(nameof(filePath));
return Open(new FileInfo(filePath), readerOptions ?? new ReaderOptions());
return OpenArchive(new FileInfo(filePath), readerOptions ?? new ReaderOptions());
}
public static IWritableArchive Open(FileInfo fileInfo, ReaderOptions? readerOptions = null)
public static IWritableArchive OpenArchive(
FileInfo fileInfo,
ReaderOptions? readerOptions = null
)
{
fileInfo.NotNull(nameof(fileInfo));
return new GZipArchive(
@@ -52,7 +55,7 @@ public partial class GZipArchive
);
}
public static IWritableArchive Open(
public static IWritableArchive OpenArchive(
IEnumerable<FileInfo> fileInfos,
ReaderOptions? readerOptions = null
)
@@ -68,7 +71,7 @@ public partial class GZipArchive
);
}
public static IWritableArchive Open(
public static IWritableArchive OpenArchive(
IEnumerable<Stream> streams,
ReaderOptions? readerOptions = null
)
@@ -84,7 +87,7 @@ public partial class GZipArchive
);
}
public static IWritableArchive Open(Stream stream, ReaderOptions? readerOptions = null)
public static IWritableArchive OpenArchive(Stream stream, ReaderOptions? readerOptions = null)
{
stream.NotNull(nameof(stream));
@@ -98,47 +101,49 @@ public partial class GZipArchive
);
}
public static IWritableAsyncArchive OpenAsync(
public static IWritableAsyncArchive OpenAsyncArchive(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IWritableAsyncArchive)Open(stream, readerOptions);
return (IWritableAsyncArchive)OpenArchive(stream, readerOptions);
}
public static IWritableAsyncArchive OpenAsync(
public static IWritableAsyncArchive OpenAsyncArchive(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IWritableAsyncArchive)Open(fileInfo, readerOptions);
return (IWritableAsyncArchive)OpenArchive(fileInfo, readerOptions);
}
public static IWritableAsyncArchive OpenAsync(
public static IWritableAsyncArchive OpenAsyncArchive(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IWritableAsyncArchive)Open(streams, readerOptions);
return (IWritableAsyncArchive)OpenArchive(streams, readerOptions);
}
public static IWritableAsyncArchive OpenAsync(
public static IWritableAsyncArchive OpenAsyncArchive(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IWritableAsyncArchive)Open(fileInfos, readerOptions);
return (IWritableAsyncArchive)OpenArchive(fileInfos, readerOptions);
}
public static GZipArchive Create() => new();
public static IWritableArchive CreateArchive() => new GZipArchive();
public static IWritableAsyncArchive CreateAsyncArchive() => new GZipArchive();
public static bool IsGZipFile(string filePath) => IsGZipFile(new FileInfo(filePath));

View File

@@ -138,13 +138,13 @@ public partial class GZipArchive : AbstractWritableArchive<GZipArchiveEntry, GZi
{
var stream = Volumes.Single().Stream;
stream.Position = 0;
return GZipReader.Open(stream);
return GZipReader.OpenReader(stream);
}
protected override ValueTask<IAsyncReader> CreateReaderForSolidExtractionAsync()
{
var stream = Volumes.Single().Stream;
stream.Position = 0;
return new((IAsyncReader)GZipReader.Open(stream));
return new((IAsyncReader)GZipReader.OpenReader(stream));
}
}

View File

@@ -44,4 +44,12 @@ public interface IArchive : IDisposable
/// Returns whether the archive is encrypted.
/// </summary>
bool IsEncrypted { get; }
/// <summary>
/// Returns whether multi-threaded extraction is supported for this archive.
/// Multi-threading is supported when the archive is opened from a FileInfo or file path
/// (not a stream) and the format supports random access (e.g., Zip, Tar, Rar).
/// SOLID archives (some Rar, all 7Zip) should use sequential extraction for best performance.
/// </summary>
bool SupportsMultiThreadedExtraction { get; }
}

View File

@@ -25,21 +25,21 @@ public interface IArchiveFactory : IFactory
/// </summary>
/// <param name="stream">An open, readable and seekable stream.</param>
/// <param name="readerOptions">reading options.</param>
IArchive Open(Stream stream, ReaderOptions? readerOptions = null);
IArchive OpenArchive(Stream stream, ReaderOptions? readerOptions = null);
/// <summary>
/// Opens an Archive for random access asynchronously.
/// </summary>
/// <param name="stream">An open, readable and seekable stream.</param>
/// <param name="readerOptions">reading options.</param>
IAsyncArchive OpenAsync(Stream stream, ReaderOptions? readerOptions = null);
IAsyncArchive OpenAsyncArchive(Stream stream, ReaderOptions? readerOptions = null);
/// <summary>
/// Constructor with a FileInfo object to an existing file.
/// </summary>
/// <param name="fileInfo">the file to open.</param>
/// <param name="readerOptions">reading options.</param>
IArchive Open(FileInfo fileInfo, ReaderOptions? readerOptions = null);
IArchive OpenArchive(FileInfo fileInfo, ReaderOptions? readerOptions = null);
/// <summary>
/// Opens an Archive from a FileInfo object asynchronously.
@@ -47,7 +47,7 @@ public interface IArchiveFactory : IFactory
/// <param name="fileInfo">the file to open.</param>
/// <param name="readerOptions">reading options.</param>
/// <param name="cancellationToken">Cancellation token.</param>
IAsyncArchive OpenAsync(
IAsyncArchive OpenAsyncArchive(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default

View File

@@ -9,28 +9,32 @@ public interface IArchiveOpenable<TSync, TASync>
where TSync : IArchive
where TASync : IAsyncArchive
{
public static abstract TSync Open(string filePath, ReaderOptions? readerOptions = null);
public static abstract TSync OpenArchive(string filePath, ReaderOptions? readerOptions = null);
public static abstract TSync Open(FileInfo fileInfo, ReaderOptions? readerOptions = null);
public static abstract TSync OpenArchive(
FileInfo fileInfo,
ReaderOptions? readerOptions = null
);
public static abstract TSync Open(Stream stream, ReaderOptions? readerOptions = null);
public static abstract TSync OpenArchive(Stream stream, ReaderOptions? readerOptions = null);
public static abstract TASync OpenAsync(
public static abstract TASync OpenAsyncArchive(
string path,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
);
public static abstract TASync OpenAsync(
public static abstract TASync OpenAsyncArchive(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
);
public static abstract TASync OpenAsync(
public static abstract TASync OpenAsyncArchive(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
);
}
#endif

View File

@@ -26,21 +26,24 @@ public interface IMultiArchiveFactory : IFactory
/// </summary>
/// <param name="streams"></param>
/// <param name="readerOptions">reading options.</param>
IArchive Open(IReadOnlyList<Stream> streams, ReaderOptions? readerOptions = null);
IArchive OpenArchive(IReadOnlyList<Stream> streams, ReaderOptions? readerOptions = null);
/// <summary>
/// Opens a multi-part archive from streams asynchronously.
/// </summary>
/// <param name="streams"></param>
/// <param name="readerOptions">reading options.</param>
IAsyncArchive OpenAsync(IReadOnlyList<Stream> streams, ReaderOptions? readerOptions = null);
IAsyncArchive OpenAsyncArchive(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null
);
/// <summary>
/// Constructor with IEnumerable Stream objects, multi and split support.
/// </summary>
/// <param name="fileInfos"></param>
/// <param name="readerOptions">reading options.</param>
IArchive Open(IReadOnlyList<FileInfo> fileInfos, ReaderOptions? readerOptions = null);
IArchive OpenArchive(IReadOnlyList<FileInfo> fileInfos, ReaderOptions? readerOptions = null);
/// <summary>
/// Opens a multi-part archive from files asynchronously.
@@ -48,7 +51,7 @@ public interface IMultiArchiveFactory : IFactory
/// <param name="fileInfos"></param>
/// <param name="readerOptions">reading options.</param>
/// <param name="cancellationToken">Cancellation token.</param>
IAsyncArchive OpenAsync(
IAsyncArchive OpenAsyncArchive(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default

View File

@@ -10,23 +10,23 @@ public interface IMultiArchiveOpenable<TSync, TASync>
where TSync : IArchive
where TASync : IAsyncArchive
{
public static abstract TSync Open(
public static abstract TSync OpenArchive(
IEnumerable<FileInfo> fileInfos,
ReaderOptions? readerOptions = null
);
public static abstract TSync Open(
public static abstract TSync OpenArchive(
IEnumerable<Stream> streams,
ReaderOptions? readerOptions = null
);
public static abstract TASync OpenAsync(
public static abstract TASync OpenAsyncArchive(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
);
public static abstract TASync OpenAsync(
public static abstract TASync OpenAsyncArchive(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default

View File

@@ -34,6 +34,13 @@ public static class IWritableArchiveCommonExtensions
public IArchiveEntry AddEntry(string key, string file) =>
writableArchive.AddEntry(key, new FileInfo(file));
public IArchiveEntry AddEntry(
string key,
Stream source,
long size = 0,
DateTime? modified = null
) => writableArchive.AddEntry(key, source, false, size, modified);
public IArchiveEntry AddEntry(string key, FileInfo fileInfo)
{
if (!fileInfo.Exists)

View File

@@ -0,0 +1,10 @@
#if NET8_0_OR_GREATER
namespace SharpCompress.Archives;
public interface IWritableArchiveOpenable
: IArchiveOpenable<IWritableArchive, IWritableAsyncArchive>
{
public static abstract IWritableArchive CreateArchive();
public static abstract IWritableAsyncArchive CreateAsyncArchive();
}
#endif

View File

@@ -16,5 +16,5 @@ public interface IWriteableArchiveFactory : Factories.IFactory
/// Creates a new, empty archive, ready to be written.
/// </summary>
/// <returns></returns>
IWritableArchive CreateWriteableArchive();
IWritableArchive CreateArchive();
}

View File

@@ -19,7 +19,7 @@ public partial class RarArchive
IMultiArchiveOpenable<IRarArchive, IRarAsyncArchive>
#endif
{
public static IRarAsyncArchive OpenAsync(
public static IRarAsyncArchive OpenAsyncArchive(
string path,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
@@ -27,10 +27,10 @@ public partial class RarArchive
{
cancellationToken.ThrowIfCancellationRequested();
path.NotNullOrEmpty(nameof(path));
return (IRarAsyncArchive)Open(new FileInfo(path), readerOptions);
return (IRarAsyncArchive)OpenArchive(new FileInfo(path), readerOptions);
}
public static IRarArchive Open(string filePath, ReaderOptions? options = null)
public static IRarArchive OpenArchive(string filePath, ReaderOptions? options = null)
{
filePath.NotNullOrEmpty(nameof(filePath));
var fileInfo = new FileInfo(filePath);
@@ -43,7 +43,7 @@ public partial class RarArchive
);
}
public static IRarArchive Open(FileInfo fileInfo, ReaderOptions? options = null)
public static IRarArchive OpenArchive(FileInfo fileInfo, ReaderOptions? options = null)
{
fileInfo.NotNull(nameof(fileInfo));
return new RarArchive(
@@ -55,7 +55,7 @@ public partial class RarArchive
);
}
public static IRarArchive Open(Stream stream, ReaderOptions? options = null)
public static IRarArchive OpenArchive(Stream stream, ReaderOptions? options = null)
{
stream.NotNull(nameof(stream));
@@ -67,7 +67,7 @@ public partial class RarArchive
return new RarArchive(new SourceStream(stream, _ => null, options ?? new ReaderOptions()));
}
public static IRarArchive Open(
public static IRarArchive OpenArchive(
IEnumerable<FileInfo> fileInfos,
ReaderOptions? readerOptions = null
)
@@ -83,7 +83,10 @@ public partial class RarArchive
);
}
public static IRarArchive Open(IEnumerable<Stream> streams, ReaderOptions? readerOptions = null)
public static IRarArchive OpenArchive(
IEnumerable<Stream> streams,
ReaderOptions? readerOptions = null
)
{
streams.NotNull(nameof(streams));
var strms = streams.ToArray();
@@ -96,44 +99,44 @@ public partial class RarArchive
);
}
public static IRarAsyncArchive OpenAsync(
public static IRarAsyncArchive OpenAsyncArchive(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IRarAsyncArchive)Open(stream, readerOptions);
return (IRarAsyncArchive)OpenArchive(stream, readerOptions);
}
public static IRarAsyncArchive OpenAsync(
public static IRarAsyncArchive OpenAsyncArchive(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IRarAsyncArchive)Open(fileInfo, readerOptions);
return (IRarAsyncArchive)OpenArchive(fileInfo, readerOptions);
}
public static IRarAsyncArchive OpenAsync(
public static IRarAsyncArchive OpenAsyncArchive(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IRarAsyncArchive)Open(streams, readerOptions);
return (IRarAsyncArchive)OpenArchive(streams, readerOptions);
}
public static IRarAsyncArchive OpenAsync(
public static IRarAsyncArchive OpenAsyncArchive(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IRarAsyncArchive)Open(fileInfos, readerOptions);
return (IRarAsyncArchive)OpenArchive(fileInfos, readerOptions);
}
public static bool IsRarFile(string filePath) => IsRarFile(new FileInfo(filePath));

View File

@@ -101,12 +101,12 @@ public partial class RarArchive : AbstractArchive<RarArchiveEntry, RarVolume>, I
volume.Stream.Position = 0;
return volume.Stream;
});
return (RarReader)RarReader.Open(streams, ReaderOptions);
return (RarReader)RarReader.OpenReader(streams, ReaderOptions);
}
var stream = Volumes.First().Stream;
stream.Position = 0;
return (RarReader)RarReader.Open(stream, ReaderOptions);
return (RarReader)RarReader.OpenReader(stream, ReaderOptions);
}
public override bool IsSolid => Volumes.First().IsSolidArchive;

View File

@@ -1,6 +1,7 @@
using System.IO;
using SharpCompress.Common.Rar;
using SharpCompress.Common.Rar.Headers;
using SharpCompress.IO;
namespace SharpCompress.Archives.Rar;
@@ -24,6 +25,76 @@ internal class SeekableFilePart : RarFilePart
internal override Stream GetCompressedStream()
{
Stream streamToUse;
// If the stream is a SourceStream in file mode with multi-threading enabled,
// create an independent stream to support concurrent extraction
if (
_stream is SourceStream sourceStream
&& sourceStream.IsFileMode
&& sourceStream.ReaderOptions.EnableMultiThreadedExtraction
)
{
var independentStream = sourceStream.CreateIndependentStream(0);
if (independentStream is not null)
{
streamToUse = independentStream;
streamToUse.Position = FileHeader.DataStartPosition;
if (FileHeader.R4Salt != null)
{
var cryptKey = new CryptKey3(_password!);
return new RarCryptoWrapper(streamToUse, FileHeader.R4Salt, cryptKey);
}
if (FileHeader.Rar5CryptoInfo != null)
{
var cryptKey = new CryptKey5(_password!, FileHeader.Rar5CryptoInfo);
return new RarCryptoWrapper(
streamToUse,
FileHeader.Rar5CryptoInfo.Salt,
cryptKey
);
}
return streamToUse;
}
}
// Check if the stream wraps a FileStream
Stream? underlyingStream = _stream;
if (_stream is IStreamStack streamStack)
{
underlyingStream = streamStack.BaseStream();
}
if (underlyingStream is FileStream fileStream)
{
// Create a new independent stream from the file
streamToUse = new FileStream(
fileStream.Name,
FileMode.Open,
FileAccess.Read,
FileShare.Read
);
streamToUse.Position = FileHeader.DataStartPosition;
if (FileHeader.R4Salt != null)
{
var cryptKey = new CryptKey3(_password!);
return new RarCryptoWrapper(streamToUse, FileHeader.R4Salt, cryptKey);
}
if (FileHeader.Rar5CryptoInfo != null)
{
var cryptKey = new CryptKey5(_password!, FileHeader.Rar5CryptoInfo);
return new RarCryptoWrapper(streamToUse, FileHeader.Rar5CryptoInfo.Salt, cryptKey);
}
return streamToUse;
}
// Fall back to existing behavior for stream-based sources
_stream.Position = FileHeader.DataStartPosition;
if (FileHeader.R4Salt != null)

View File

@@ -18,7 +18,7 @@ public partial class SevenZipArchive
IMultiArchiveOpenable<IArchive, IAsyncArchive>
#endif
{
public static IAsyncArchive OpenAsync(
public static IAsyncArchive OpenAsyncArchive(
string path,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
@@ -26,16 +26,16 @@ public partial class SevenZipArchive
{
cancellationToken.ThrowIfCancellationRequested();
path.NotNullOrEmpty("path");
return (IAsyncArchive)Open(new FileInfo(path), readerOptions ?? new ReaderOptions());
return (IAsyncArchive)OpenArchive(new FileInfo(path), readerOptions ?? new ReaderOptions());
}
public static IArchive Open(string filePath, ReaderOptions? readerOptions = null)
public static IArchive OpenArchive(string filePath, ReaderOptions? readerOptions = null)
{
filePath.NotNullOrEmpty("filePath");
return Open(new FileInfo(filePath), readerOptions ?? new ReaderOptions());
return OpenArchive(new FileInfo(filePath), readerOptions ?? new ReaderOptions());
}
public static IArchive Open(FileInfo fileInfo, ReaderOptions? readerOptions = null)
public static IArchive OpenArchive(FileInfo fileInfo, ReaderOptions? readerOptions = null)
{
fileInfo.NotNull("fileInfo");
return new SevenZipArchive(
@@ -47,7 +47,7 @@ public partial class SevenZipArchive
);
}
public static IArchive Open(
public static IArchive OpenArchive(
IEnumerable<FileInfo> fileInfos,
ReaderOptions? readerOptions = null
)
@@ -63,7 +63,10 @@ public partial class SevenZipArchive
);
}
public static IArchive Open(IEnumerable<Stream> streams, ReaderOptions? readerOptions = null)
public static IArchive OpenArchive(
IEnumerable<Stream> streams,
ReaderOptions? readerOptions = null
)
{
streams.NotNull(nameof(streams));
var strms = streams.ToArray();
@@ -76,7 +79,7 @@ public partial class SevenZipArchive
);
}
public static IArchive Open(Stream stream, ReaderOptions? readerOptions = null)
public static IArchive OpenArchive(Stream stream, ReaderOptions? readerOptions = null)
{
stream.NotNull("stream");
@@ -90,44 +93,44 @@ public partial class SevenZipArchive
);
}
public static IAsyncArchive OpenAsync(
public static IAsyncArchive OpenAsyncArchive(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncArchive)Open(stream, readerOptions);
return (IAsyncArchive)OpenArchive(stream, readerOptions);
}
public static IAsyncArchive OpenAsync(
public static IAsyncArchive OpenAsyncArchive(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncArchive)Open(fileInfo, readerOptions);
return (IAsyncArchive)OpenArchive(fileInfo, readerOptions);
}
public static IAsyncArchive OpenAsync(
public static IAsyncArchive OpenAsyncArchive(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncArchive)Open(streams, readerOptions);
return (IAsyncArchive)OpenArchive(streams, readerOptions);
}
public static IAsyncArchive OpenAsync(
public static IAsyncArchive OpenAsyncArchive(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncArchive)Open(fileInfos, readerOptions);
return (IAsyncArchive)OpenArchive(fileInfos, readerOptions);
}
public static bool IsSevenZipFile(string filePath) => IsSevenZipFile(new FileInfo(filePath));

View File

@@ -184,7 +184,7 @@ public partial class SevenZipArchive : AbstractArchive<SevenZipArchiveEntry, Sev
return Task.CompletedTask;
}
#if !NETFRAMEWORK && !NETSTANDARD2_0
#if !LEGACY_DOTNET
public override ValueTask<int> ReadAsync(
Memory<byte> buffer,
CancellationToken cancellationToken = default

View File

@@ -16,17 +16,20 @@ namespace SharpCompress.Archives.Tar;
public partial class TarArchive
#if NET8_0_OR_GREATER
: IArchiveOpenable<IWritableArchive, IWritableAsyncArchive>,
: IWritableArchiveOpenable,
IMultiArchiveOpenable<IWritableArchive, IWritableAsyncArchive>
#endif
{
public static IWritableArchive Open(string filePath, ReaderOptions? readerOptions = null)
public static IWritableArchive OpenArchive(string filePath, ReaderOptions? readerOptions = null)
{
filePath.NotNullOrEmpty(nameof(filePath));
return Open(new FileInfo(filePath), readerOptions ?? new ReaderOptions());
return OpenArchive(new FileInfo(filePath), readerOptions ?? new ReaderOptions());
}
public static IWritableArchive Open(FileInfo fileInfo, ReaderOptions? readerOptions = null)
public static IWritableArchive OpenArchive(
FileInfo fileInfo,
ReaderOptions? readerOptions = null
)
{
fileInfo.NotNull(nameof(fileInfo));
return new TarArchive(
@@ -38,7 +41,7 @@ public partial class TarArchive
);
}
public static IWritableArchive Open(
public static IWritableArchive OpenArchive(
IEnumerable<FileInfo> fileInfos,
ReaderOptions? readerOptions = null
)
@@ -54,7 +57,7 @@ public partial class TarArchive
);
}
public static IWritableArchive Open(
public static IWritableArchive OpenArchive(
IEnumerable<Stream> streams,
ReaderOptions? readerOptions = null
)
@@ -70,7 +73,7 @@ public partial class TarArchive
);
}
public static IWritableArchive Open(Stream stream, ReaderOptions? readerOptions = null)
public static IWritableArchive OpenArchive(Stream stream, ReaderOptions? readerOptions = null)
{
stream.NotNull(nameof(stream));
@@ -84,54 +87,54 @@ public partial class TarArchive
);
}
public static IWritableAsyncArchive OpenAsync(
public static IWritableAsyncArchive OpenAsyncArchive(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IWritableAsyncArchive)Open(stream, readerOptions);
return (IWritableAsyncArchive)OpenArchive(stream, readerOptions);
}
public static IWritableAsyncArchive OpenAsync(
public static IWritableAsyncArchive OpenAsyncArchive(
string path,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IWritableAsyncArchive)Open(new FileInfo(path), readerOptions);
return (IWritableAsyncArchive)OpenArchive(new FileInfo(path), readerOptions);
}
public static IWritableAsyncArchive OpenAsync(
public static IWritableAsyncArchive OpenAsyncArchive(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IWritableAsyncArchive)Open(fileInfo, readerOptions);
return (IWritableAsyncArchive)OpenArchive(fileInfo, readerOptions);
}
public static IWritableAsyncArchive OpenAsync(
public static IWritableAsyncArchive OpenAsyncArchive(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IWritableAsyncArchive)Open(streams, readerOptions);
return (IWritableAsyncArchive)OpenArchive(streams, readerOptions);
}
public static IWritableAsyncArchive OpenAsync(
public static IWritableAsyncArchive OpenAsyncArchive(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IWritableAsyncArchive)Open(fileInfos, readerOptions);
return (IWritableAsyncArchive)OpenArchive(fileInfos, readerOptions);
}
public static bool IsTarFile(string filePath) => IsTarFile(new FileInfo(filePath));
@@ -162,5 +165,7 @@ public partial class TarArchive
return false;
}
public static TarArchive Create() => new();
public static IWritableArchive CreateArchive() => new TarArchive();
public static IWritableAsyncArchive CreateAsyncArchive() => new TarArchive();
}

View File

@@ -180,13 +180,13 @@ public partial class TarArchive : AbstractWritableArchive<TarArchiveEntry, TarVo
{
var stream = Volumes.Single().Stream;
stream.Position = 0;
return TarReader.Open(stream);
return TarReader.OpenReader(stream);
}
protected override ValueTask<IAsyncReader> CreateReaderForSolidExtractionAsync()
{
var stream = Volumes.Single().Stream;
stream.Position = 0;
return new((IAsyncReader)TarReader.Open(stream));
return new((IAsyncReader)TarReader.OpenReader(stream));
}
}

View File

@@ -14,17 +14,20 @@ namespace SharpCompress.Archives.Zip;
public partial class ZipArchive
#if NET8_0_OR_GREATER
: IArchiveOpenable<IWritableArchive, IWritableAsyncArchive>,
: IWritableArchiveOpenable,
IMultiArchiveOpenable<IWritableArchive, IWritableAsyncArchive>
#endif
{
public static IWritableArchive Open(string filePath, ReaderOptions? readerOptions = null)
public static IWritableArchive OpenArchive(string filePath, ReaderOptions? readerOptions = null)
{
filePath.NotNullOrEmpty(nameof(filePath));
return Open(new FileInfo(filePath), readerOptions ?? new ReaderOptions());
return OpenArchive(new FileInfo(filePath), readerOptions ?? new ReaderOptions());
}
public static IWritableArchive Open(FileInfo fileInfo, ReaderOptions? readerOptions = null)
public static IWritableArchive OpenArchive(
FileInfo fileInfo,
ReaderOptions? readerOptions = null
)
{
fileInfo.NotNull(nameof(fileInfo));
return new ZipArchive(
@@ -36,7 +39,7 @@ public partial class ZipArchive
);
}
public static IWritableArchive Open(
public static IWritableArchive OpenArchive(
IEnumerable<FileInfo> fileInfos,
ReaderOptions? readerOptions = null
)
@@ -52,7 +55,7 @@ public partial class ZipArchive
);
}
public static IWritableArchive Open(
public static IWritableArchive OpenArchive(
IEnumerable<Stream> streams,
ReaderOptions? readerOptions = null
)
@@ -68,7 +71,7 @@ public partial class ZipArchive
);
}
public static IWritableArchive Open(Stream stream, ReaderOptions? readerOptions = null)
public static IWritableArchive OpenArchive(Stream stream, ReaderOptions? readerOptions = null)
{
stream.NotNull(nameof(stream));
@@ -82,54 +85,54 @@ public partial class ZipArchive
);
}
public static IWritableAsyncArchive OpenAsync(
public static IWritableAsyncArchive OpenAsyncArchive(
string path,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IWritableAsyncArchive)Open(path, readerOptions);
return (IWritableAsyncArchive)OpenArchive(path, readerOptions);
}
public static IWritableAsyncArchive OpenAsync(
public static IWritableAsyncArchive OpenAsyncArchive(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IWritableAsyncArchive)Open(stream, readerOptions);
return (IWritableAsyncArchive)OpenArchive(stream, readerOptions);
}
public static IWritableAsyncArchive OpenAsync(
public static IWritableAsyncArchive OpenAsyncArchive(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IWritableAsyncArchive)Open(fileInfo, readerOptions);
return (IWritableAsyncArchive)OpenArchive(fileInfo, readerOptions);
}
public static IWritableAsyncArchive OpenAsync(
public static IWritableAsyncArchive OpenAsyncArchive(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IWritableAsyncArchive)Open(streams, readerOptions);
return (IWritableAsyncArchive)OpenArchive(streams, readerOptions);
}
public static IWritableAsyncArchive OpenAsync(
public static IWritableAsyncArchive OpenAsyncArchive(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IWritableAsyncArchive)Open(fileInfos, readerOptions);
return (IWritableAsyncArchive)OpenArchive(fileInfos, readerOptions);
}
public static bool IsZipFile(
@@ -263,7 +266,9 @@ public partial class ZipArchive
}
}
public static ZipArchive Create() => new();
public static IWritableArchive CreateArchive() => new ZipArchive();
public static IWritableAsyncArchive CreateAsyncArchive() => new ZipArchive();
public static async ValueTask<bool> IsZipMultiAsync(
Stream stream,

View File

@@ -244,13 +244,13 @@ public partial class ZipArchive : AbstractWritableArchive<ZipArchiveEntry, ZipVo
{
var stream = Volumes.Single().Stream;
((IStreamStack)stream).StackSeek(0);
return ZipReader.Open(stream, ReaderOptions, Entries);
return ZipReader.OpenReader(stream, ReaderOptions, Entries);
}
protected override ValueTask<IAsyncReader> CreateReaderForSolidExtractionAsync()
{
var stream = Volumes.Single().Stream;
stream.Position = 0;
return new((IAsyncReader)ZipReader.Open(stream));
return new((IAsyncReader)ZipReader.OpenReader(stream));
}
}

View File

@@ -51,14 +51,19 @@ namespace SharpCompress.Common
return BinaryPrimitives.ReadUInt64LittleEndian(_buffer);
}
public async ValueTask ReadBytesAsync(byte[] bytes, int offset, int count, CancellationToken ct = default)
public async ValueTask ReadBytesAsync(
byte[] bytes,
int offset,
int count,
CancellationToken ct = default
)
{
await _stream.ReadExactAsync(bytes, offset, count, ct).ConfigureAwait(false);
}
public async ValueTask SkipAsync(int count, CancellationToken ct = default)
{
await _stream.SkipAsync( count, ct).ConfigureAwait(false);
await _stream.SkipAsync(count, ct).ConfigureAwait(false);
}
public void Dispose()
@@ -77,7 +82,7 @@ namespace SharpCompress.Common
}
}
#if NET6_0_OR_GREATER
#if NET8_0_OR_GREATER
public async ValueTask DisposeAsync()
{
if (_disposed)

View File

@@ -93,7 +93,7 @@ public class EntryStream : Stream, IStreamStack
_stream.Dispose();
}
#if !NETFRAMEWORK && !NETSTANDARD2_0
#if !LEGACY_DOTNET
public override async ValueTask DisposeAsync()
{
if (_isDisposed)
@@ -171,7 +171,7 @@ public class EntryStream : Stream, IStreamStack
return read;
}
#if !NETFRAMEWORK && !NETSTANDARD2_0
#if !LEGACY_DOTNET
public override async ValueTask<int> ReadAsync(
Memory<byte> buffer,
CancellationToken cancellationToken = default

View File

@@ -1,5 +1,6 @@
using System.IO;
using SharpCompress.Common.Tar.Headers;
using SharpCompress.IO;
namespace SharpCompress.Common.Tar;
@@ -20,8 +21,45 @@ internal sealed class TarFilePart : FilePart
internal override Stream GetCompressedStream()
{
if (_seekableStream != null)
if (_seekableStream is not null)
{
// If the seekable stream is a SourceStream in file mode with multi-threading enabled,
// create an independent stream to support concurrent extraction
if (
_seekableStream is SourceStream sourceStream
&& sourceStream.IsFileMode
&& sourceStream.ReaderOptions.EnableMultiThreadedExtraction
)
{
var independentStream = sourceStream.CreateIndependentStream(0);
if (independentStream is not null)
{
independentStream.Position = Header.DataStartPosition ?? 0;
return new TarReadOnlySubStream(independentStream, Header.Size);
}
}
// Check if the seekable stream wraps a FileStream
Stream? underlyingStream = _seekableStream;
if (_seekableStream is IStreamStack streamStack)
{
underlyingStream = streamStack.BaseStream();
}
if (underlyingStream is FileStream fileStream)
{
// Create a new independent stream from the file
var independentStream = new FileStream(
fileStream.Name,
FileMode.Open,
FileAccess.Read,
FileShare.Read
);
independentStream.Position = Header.DataStartPosition ?? 0;
return new TarReadOnlySubStream(independentStream, Header.Size);
}
// Fall back to existing behavior for stream-based sources
_seekableStream.Position = Header.DataStartPosition ?? 0;
return new TarReadOnlySubStream(_seekableStream, Header.Size);
}

View File

@@ -66,7 +66,7 @@ internal class TarReadOnlySubStream : SharpCompressStream, IStreamStack
base.Dispose(disposing);
}
#if !NETFRAMEWORK && !NETSTANDARD2_0
#if !LEGACY_DOTNET
public override async System.Threading.Tasks.ValueTask DisposeAsync()
{
if (_isDisposed)
@@ -170,7 +170,7 @@ internal class TarReadOnlySubStream : SharpCompressStream, IStreamStack
return read;
}
#if !NETFRAMEWORK && !NETSTANDARD2_0
#if !LEGACY_DOTNET
public override async System.Threading.Tasks.ValueTask<int> ReadAsync(
System.Memory<byte> buffer,
System.Threading.CancellationToken cancellationToken = default

View File

@@ -56,7 +56,7 @@ internal class DirectoryEntryHeader : ZipFileEntry
var name = new byte[nameLength];
var extra = new byte[extraLength];
var comment = new byte[commentLength];
await reader.ReadBytesAsync(name,0 ,nameLength);
await reader.ReadBytesAsync(name, 0, nameLength);
await reader.ReadBytesAsync(extra, 0, extraLength);
await reader.ReadBytesAsync(comment, 0, commentLength);

View File

@@ -39,8 +39,8 @@ internal class LocalEntryHeader(IArchiveEncoding archiveEncoding)
var extraLength = await reader.ReadUInt16Async();
var name = new byte[nameLength];
var extra = new byte[extraLength];
await reader.ReadBytesAsync(name,0 ,nameLength);
await reader.ReadBytesAsync(extra, 0, extraLength);
await reader.ReadBytesAsync(name, 0, nameLength);
await reader.ReadBytesAsync(extra, 0, extraLength);
ProcessReadData(name, extra);
}

View File

@@ -39,11 +39,10 @@ internal class Zip64DirectoryEndHeader : ZipHeader
DirectorySize = (long)await reader.ReadUInt64Async();
DirectoryStartOffsetRelativeToDisk = (long)await reader.ReadUInt64Async();
var size = (int)(
SizeOfDirectoryEndRecord
- SIZE_OF_FIXED_HEADER_DATA_EXCEPT_SIGNATURE_AND_SIZE_FIELDS
SizeOfDirectoryEndRecord - SIZE_OF_FIXED_HEADER_DATA_EXCEPT_SIGNATURE_AND_SIZE_FIELDS
);
DataSector = new byte[size];
await reader.ReadBytesAsync(DataSector, 0, size);
await reader.ReadBytesAsync(DataSector, 0, size);
}
private const int SIZE_OF_FIXED_HEADER_DATA_EXCEPT_SIGNATURE_AND_SIZE_FIELDS = 44;

View File

@@ -2,13 +2,16 @@ using System.IO;
using System.Threading;
using System.Threading.Tasks;
using SharpCompress.Common.Zip.Headers;
using SharpCompress.IO;
namespace SharpCompress.Common.Zip;
internal class SeekableZipFilePart : ZipFilePart
{
private bool _isLocalHeaderLoaded;
private volatile bool _isLocalHeaderLoaded;
private readonly SeekableZipHeaderFactory _headerFactory;
private readonly object _headerLock = new();
private readonly SemaphoreSlim _asyncHeaderSemaphore = new(1, 1);
internal SeekableZipFilePart(
SeekableZipHeaderFactory headerFactory,
@@ -21,8 +24,14 @@ internal class SeekableZipFilePart : ZipFilePart
{
if (!_isLocalHeaderLoaded)
{
LoadLocalHeader();
_isLocalHeaderLoaded = true;
lock (_headerLock)
{
if (!_isLocalHeaderLoaded)
{
LoadLocalHeader();
_isLocalHeaderLoaded = true;
}
}
}
return base.GetCompressedStream();
}
@@ -33,22 +42,173 @@ internal class SeekableZipFilePart : ZipFilePart
{
if (!_isLocalHeaderLoaded)
{
await LoadLocalHeaderAsync(cancellationToken);
_isLocalHeaderLoaded = true;
await _asyncHeaderSemaphore.WaitAsync(cancellationToken);
try
{
if (!_isLocalHeaderLoaded)
{
await LoadLocalHeaderAsync(cancellationToken);
_isLocalHeaderLoaded = true;
}
}
finally
{
_asyncHeaderSemaphore.Release();
}
}
return await base.GetCompressedStreamAsync(cancellationToken);
}
private void LoadLocalHeader() =>
Header = _headerFactory.GetLocalHeader(BaseStream, (DirectoryEntryHeader)Header);
private void LoadLocalHeader()
{
// Use an independent stream for loading the header if multi-threading is enabled
Stream streamToUse = BaseStream;
bool disposeStream = false;
private async ValueTask LoadLocalHeaderAsync(CancellationToken cancellationToken = default) =>
Header = await _headerFactory.GetLocalHeaderAsync(BaseStream, (DirectoryEntryHeader)Header);
if (
BaseStream is SourceStream sourceStream
&& sourceStream.IsFileMode
&& sourceStream.ReaderOptions.EnableMultiThreadedExtraction
)
{
var independentStream = sourceStream.CreateIndependentStream(0);
if (independentStream is not null)
{
streamToUse = independentStream;
disposeStream = true;
}
}
else
{
// Check if BaseStream wraps a FileStream
Stream? underlyingStream = BaseStream;
if (BaseStream is IStreamStack streamStack)
{
underlyingStream = streamStack.BaseStream();
}
if (underlyingStream is FileStream fileStream)
{
streamToUse = new FileStream(
fileStream.Name,
FileMode.Open,
FileAccess.Read,
FileShare.Read
);
disposeStream = true;
}
}
try
{
Header = _headerFactory.GetLocalHeader(streamToUse, (DirectoryEntryHeader)Header);
}
finally
{
if (disposeStream)
{
streamToUse.Dispose();
}
}
}
private async ValueTask LoadLocalHeaderAsync(CancellationToken cancellationToken = default)
{
// Use an independent stream for loading the header if multi-threading is enabled
Stream streamToUse = BaseStream;
bool disposeStream = false;
if (
BaseStream is SourceStream sourceStream
&& sourceStream.IsFileMode
&& sourceStream.ReaderOptions.EnableMultiThreadedExtraction
)
{
var independentStream = sourceStream.CreateIndependentStream(0);
if (independentStream is not null)
{
streamToUse = independentStream;
disposeStream = true;
}
}
else
{
// Check if BaseStream wraps a FileStream
Stream? underlyingStream = BaseStream;
if (BaseStream is IStreamStack streamStack)
{
underlyingStream = streamStack.BaseStream();
}
if (underlyingStream is FileStream fileStream)
{
streamToUse = new FileStream(
fileStream.Name,
FileMode.Open,
FileAccess.Read,
FileShare.Read
);
disposeStream = true;
}
}
try
{
Header = await _headerFactory.GetLocalHeaderAsync(
streamToUse,
(DirectoryEntryHeader)Header
);
}
finally
{
if (disposeStream)
{
streamToUse.Dispose();
}
}
}
protected override Stream CreateBaseStream()
{
BaseStream.Position = Header.DataStartPosition.NotNull();
// If BaseStream is a SourceStream in file mode with multi-threading enabled,
// create an independent stream to support concurrent extraction
if (
BaseStream is SourceStream sourceStream
&& sourceStream.IsFileMode
&& sourceStream.ReaderOptions.EnableMultiThreadedExtraction
)
{
// Create a new independent stream for this entry
var independentStream = sourceStream.CreateIndependentStream(0);
if (independentStream is not null)
{
independentStream.Position = Header.DataStartPosition.NotNull();
return independentStream;
}
}
// Check if BaseStream wraps a FileStream (for multi-volume archives)
Stream? underlyingStream = BaseStream;
if (BaseStream is IStreamStack streamStack)
{
underlyingStream = streamStack.BaseStream();
}
if (underlyingStream is FileStream fileStream)
{
// Create a new independent stream from the file
var independentStream = new FileStream(
fileStream.Name,
FileMode.Open,
FileAccess.Read,
FileShare.Read
);
independentStream.Position = Header.DataStartPosition.NotNull();
return independentStream;
}
// Fall back to existing behavior for stream-based sources
BaseStream.Position = Header.DataStartPosition.NotNull();
return BaseStream;
}
}

View File

@@ -156,7 +156,6 @@ internal sealed class SeekableZipHeaderFactory : ZipHeaderFactory
}
}
private static bool IsMatch(Span<byte> haystack, int position, byte[] needle)
{
for (var i = 0; i < needle.Length; i++)

View File

@@ -20,7 +20,7 @@ internal class WinzipAesEncryptionData
{
_keySize = keySize;
#if NETFRAMEWORK || NETSTANDARD2_0
#if LEGACY_DOTNET
var rfc2898 = new Rfc2898DeriveBytes(password, salt, RFC2898_ITERATIONS);
KeyBytes = rfc2898.GetBytes(KeySizeInBytes);
IvBytes = rfc2898.GetBytes(KeySizeInBytes);

View File

@@ -98,7 +98,7 @@ public sealed class BZip2Stream : Stream, IStreamStack
public override void SetLength(long value) => stream.SetLength(value);
#if !NETFRAMEWORK && !NETSTANDARD2_0
#if !LEGACY_DOTNET
public override int Read(Span<byte> buffer) => stream.Read(buffer);

View File

@@ -299,7 +299,7 @@ public class DeflateStream : Stream, IStreamStack
await _baseStream.FlushAsync(cancellationToken).ConfigureAwait(false);
}
#if !NETFRAMEWORK && !NETSTANDARD2_0
#if !LEGACY_DOTNET
public override async ValueTask DisposeAsync()
{
if (_disposed)
@@ -370,7 +370,7 @@ public class DeflateStream : Stream, IStreamStack
.ConfigureAwait(false);
}
#if !NETFRAMEWORK && !NETSTANDARD2_0
#if !LEGACY_DOTNET
public override async ValueTask<int> ReadAsync(
Memory<byte> buffer,
CancellationToken cancellationToken = default
@@ -461,7 +461,7 @@ public class DeflateStream : Stream, IStreamStack
.ConfigureAwait(false);
}
#if !NETFRAMEWORK && !NETSTANDARD2_0
#if !LEGACY_DOTNET
public override async ValueTask WriteAsync(
ReadOnlyMemory<byte> buffer,
CancellationToken cancellationToken = default

View File

@@ -345,7 +345,7 @@ public class GZipStream : Stream, IStreamStack
return n;
}
#if !NETFRAMEWORK && !NETSTANDARD2_0
#if !LEGACY_DOTNET
public override async ValueTask<int> ReadAsync(
Memory<byte> buffer,
CancellationToken cancellationToken = default
@@ -454,7 +454,7 @@ public class GZipStream : Stream, IStreamStack
await BaseStream.WriteAsync(buffer, offset, count, cancellationToken).ConfigureAwait(false);
}
#if !NETFRAMEWORK && !NETSTANDARD2_0
#if !LEGACY_DOTNET
public override async ValueTask WriteAsync(
ReadOnlyMemory<byte> buffer,
CancellationToken cancellationToken = default

View File

@@ -776,11 +776,16 @@ internal sealed class InflateBlocks
// update check information
if (checkfn != null)
{
_codec._adler32 = check = Adler32.Calculate(check, window.Memory.Span.Slice(readAt, nBytes));
_codec._adler32 = check = Adler32.Calculate(
check,
window.Memory.Span.Slice(readAt, nBytes)
);
}
// copy as far as end of window
window.Memory.Span.Slice(readAt, nBytes).CopyTo(_codec.OutputBuffer.AsSpan(_codec.NextOut));
window
.Memory.Span.Slice(readAt, nBytes)
.CopyTo(_codec.OutputBuffer.AsSpan(_codec.NextOut));
_codec.NextOut += nBytes;
readAt += nBytes;
@@ -1469,7 +1474,8 @@ internal sealed class InflateCodes
}
else
{
s.window.Memory.Span.Slice(r, 2).CopyTo(s.window.Memory.Span.Slice(q));
s.window.Memory.Span.Slice(r, 2)
.CopyTo(s.window.Memory.Span.Slice(q));
q += 2;
r += 2;
c -= 2;
@@ -1497,7 +1503,8 @@ internal sealed class InflateCodes
}
else
{
s.window.Memory.Span.Slice(r, e).CopyTo(s.window.Memory.Span.Slice(q));
s.window.Memory.Span.Slice(r, e)
.CopyTo(s.window.Memory.Span.Slice(q));
q += e;
r += e;
e = 0;
@@ -1516,7 +1523,8 @@ internal sealed class InflateCodes
}
else
{
s.window.Memory.Span.Slice(r, c).CopyTo(s.window.Memory.Span.Slice(q));
s.window.Memory.Span.Slice(r, c)
.CopyTo(s.window.Memory.Span.Slice(q));
q += c;
r += c;
c = 0;

View File

@@ -552,7 +552,7 @@ internal class ZlibBaseStream : Stream, IStreamStack
}
}
#if !NETFRAMEWORK && !NETSTANDARD2_0
#if !LEGACY_DOTNET
public override async ValueTask DisposeAsync()
{
if (isDisposed)
@@ -1171,7 +1171,7 @@ internal class ZlibBaseStream : Stream, IStreamStack
return rc;
}
#if !NETFRAMEWORK && !NETSTANDARD2_0
#if !LEGACY_DOTNET
public override async ValueTask<int> ReadAsync(
Memory<byte> buffer,
CancellationToken cancellationToken = default

View File

@@ -108,13 +108,9 @@ internal static class ZlibConstants
public const int Z_BUF_ERROR = -5;
/// <summary>
/// The size of the working buffer used in the ZlibCodec class. Defaults to 8192 bytes.
/// The size of the working buffer used in the ZlibCodec class. Defaults to 16384 bytes.
/// </summary>
#if NETCF
public const int WorkingBufferSizeDefault = 8192;
#else
public const int WorkingBufferSizeDefault = 16384;
#endif
/// <summary>
/// The minimum size of the working buffer used in the ZlibCodec class. Currently it is 128 bytes.

View File

@@ -277,7 +277,7 @@ public class ZlibStream : Stream, IStreamStack
await _baseStream.FlushAsync(cancellationToken).ConfigureAwait(false);
}
#if !NETFRAMEWORK && !NETSTANDARD2_0
#if !LEGACY_DOTNET
public override async ValueTask DisposeAsync()
{
if (_disposed)
@@ -347,7 +347,7 @@ public class ZlibStream : Stream, IStreamStack
.ConfigureAwait(false);
}
#if !NETFRAMEWORK && !NETSTANDARD2_0
#if !LEGACY_DOTNET
public override async ValueTask<int> ReadAsync(
Memory<byte> buffer,
CancellationToken cancellationToken = default
@@ -431,7 +431,7 @@ public class ZlibStream : Stream, IStreamStack
.ConfigureAwait(false);
}
#if !NETFRAMEWORK && !NETSTANDARD2_0
#if !LEGACY_DOTNET
public override async ValueTask WriteAsync(
ReadOnlyMemory<byte> buffer,
CancellationToken cancellationToken = default

View File

@@ -200,7 +200,7 @@ public sealed class Deflate64Stream : Stream, IStreamStack
return count - remainingCount;
}
#if !NETFRAMEWORK && !NETSTANDARD2_0
#if !LEGACY_DOTNET
public override async ValueTask<int> ReadAsync(
Memory<byte> buffer,
CancellationToken cancellationToken = default

View File

@@ -163,7 +163,7 @@ public sealed class LZipStream : Stream, IStreamStack
public override void SetLength(long value) => throw new NotImplementedException();
#if !NETFRAMEWORK && !NETSTANDARD2_0
#if !LEGACY_DOTNET
public override ValueTask<int> ReadAsync(
Memory<byte> buffer,

View File

@@ -201,7 +201,7 @@ public class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream
}
}
#if !NETFRAMEWORK && !NETSTANDARD2_0
#if !LEGACY_DOTNET
[MemberNotNull(nameof(_outWindow))]
#endif
private void CreateDictionary()

View File

@@ -632,7 +632,7 @@ public class LzmaStream : Stream, IStreamStack
return total;
}
#if !NETFRAMEWORK && !NETSTANDARD2_0
#if !LEGACY_DOTNET
public override async ValueTask<int> ReadAsync(
Memory<byte> buffer,
CancellationToken cancellationToken = default

View File

@@ -185,7 +185,7 @@ internal sealed class MultiVolumeReadOnlyStream : Stream, IStreamStack
return totalRead;
}
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
#if !LEGACY_DOTNET
public override async System.Threading.Tasks.ValueTask<int> ReadAsync(
Memory<byte> buffer,
System.Threading.CancellationToken cancellationToken = default

View File

@@ -385,7 +385,7 @@ internal class RarBLAKE2spStream : RarStream, IStreamStack
return result;
}
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
#if !LEGACY_DOTNET
public override async System.Threading.Tasks.ValueTask<int> ReadAsync(
Memory<byte> buffer,
System.Threading.CancellationToken cancellationToken = default

View File

@@ -129,7 +129,7 @@ internal class RarCrcStream : RarStream, IStreamStack
return result;
}
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
#if !LEGACY_DOTNET
public override async System.Threading.Tasks.ValueTask<int> ReadAsync(
Memory<byte> buffer,
System.Threading.CancellationToken cancellationToken = default

View File

@@ -189,7 +189,7 @@ internal class RarStream : Stream, IStreamStack
return outTotal;
}
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
#if !LEGACY_DOTNET
public override async System.Threading.Tasks.ValueTask<int> ReadAsync(
Memory<byte> buffer,
System.Threading.CancellationToken cancellationToken = default

View File

@@ -126,7 +126,6 @@ internal sealed partial class Unpack : BitInput, IRarUnpack
private FileHeader fileHeader;
private void Init()
{
if (this.window is null)

View File

@@ -74,7 +74,7 @@ public class CompressionStream : Stream
~CompressionStream() => Dispose(false);
#if !NETSTANDARD2_0 && !NETFRAMEWORK
#if !LEGACY_DOTNET
public override async ValueTask DisposeAsync()
#else
public async ValueTask DisposeAsync()
@@ -145,7 +145,7 @@ public class CompressionStream : Stream
public override void Write(byte[] buffer, int offset, int count) =>
Write(new ReadOnlySpan<byte>(buffer, offset, count));
#if !NETSTANDARD2_0 && !NETFRAMEWORK
#if !LEGACY_DOTNET
public override void Write(ReadOnlySpan<byte> buffer) =>
WriteInternal(buffer, ZSTD_EndDirective.ZSTD_e_continue);
#else
@@ -176,7 +176,7 @@ public class CompressionStream : Stream
);
}
#if !NETSTANDARD2_0 && !NETFRAMEWORK
#if !LEGACY_DOTNET
private async ValueTask WriteInternalAsync(
ReadOnlyMemory<byte>? buffer,
ZSTD_EndDirective directive,
@@ -218,7 +218,7 @@ public class CompressionStream : Stream
);
}
#if !NETSTANDARD2_0 && !NETFRAMEWORK
#if !LEGACY_DOTNET
public override Task WriteAsync(
byte[] buffer,

View File

@@ -105,7 +105,7 @@ public class DecompressionStream : Stream
public override int Read(byte[] buffer, int offset, int count) =>
Read(new Span<byte>(buffer, offset, count));
#if !NETSTANDARD2_0 && !NETFRAMEWORK
#if !LEGACY_DOTNET
public override int Read(Span<byte> buffer)
#else
public int Read(Span<byte> buffer)
@@ -158,7 +158,7 @@ public class DecompressionStream : Stream
}
}
#if !NETSTANDARD2_0 && !NETFRAMEWORK
#if !LEGACY_DOTNET
public override Task<int> ReadAsync(
byte[] buffer,
int offset,
@@ -276,7 +276,7 @@ public class DecompressionStream : Stream
throw new ObjectDisposedException(nameof(DecompressionStream));
}
#if NETSTANDARD2_0 || NETFRAMEWORK
#if LEGACY_DOTNET
public virtual Task DisposeAsync()
{
try

View File

@@ -16,7 +16,7 @@ public static unsafe class UnsafeHelper
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void* malloc(ulong size)
{
#if NET6_0_OR_GREATER
#if NET8_0_OR_GREATER
var ptr = NativeMemory.Alloc((nuint)size);
#else
var ptr = (void*)Marshal.AllocHGlobal((nint)size);
@@ -31,7 +31,7 @@ public static unsafe class UnsafeHelper
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void* calloc(ulong num, ulong size)
{
#if NET6_0_OR_GREATER
#if NET8_0_OR_GREATER
return NativeMemory.AllocZeroed((nuint)num, (nuint)size);
#else
var total = num * size;
@@ -53,7 +53,7 @@ public static unsafe class UnsafeHelper
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void free(void* ptr)
{
#if NET6_0_OR_GREATER
#if NET8_0_OR_GREATER
NativeMemory.Free(ptr);
#else
Marshal.FreeHGlobal((IntPtr)ptr);

View File

@@ -70,7 +70,7 @@ public sealed class Crc32Stream : Stream, IStreamStack
public override void SetLength(long value) => throw new NotSupportedException();
#if !NETFRAMEWORK && !NETSTANDARD2_0
#if !LEGACY_DOTNET
public override void Write(ReadOnlySpan<byte> buffer)
{

View File

@@ -30,16 +30,16 @@ namespace SharpCompress.Factories
) => AceHeader.IsArchive(stream);
public IReader OpenReader(Stream stream, ReaderOptions? options) =>
AceReader.Open(stream, options);
AceReader.OpenReader(stream, options);
public IAsyncReader OpenReaderAsync(
public IAsyncReader OpenAsyncReader(
Stream stream,
ReaderOptions? options,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncReader)AceReader.Open(stream, options);
return (IAsyncReader)AceReader.OpenReader(stream, options);
}
public override ValueTask<bool> IsArchiveAsync(

View File

@@ -42,16 +42,16 @@ namespace SharpCompress.Factories
}
public IReader OpenReader(Stream stream, ReaderOptions? options) =>
ArcReader.Open(stream, options);
ArcReader.OpenReader(stream, options);
public IAsyncReader OpenReaderAsync(
public IAsyncReader OpenAsyncReader(
Stream stream,
ReaderOptions? options,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncReader)ArcReader.Open(stream, options);
return (IAsyncReader)ArcReader.OpenReader(stream, options);
}
public override ValueTask<bool> IsArchiveAsync(

View File

@@ -33,16 +33,16 @@ namespace SharpCompress.Factories
}
public IReader OpenReader(Stream stream, ReaderOptions? options) =>
ArjReader.Open(stream, options);
ArjReader.OpenReader(stream, options);
public IAsyncReader OpenReaderAsync(
public IAsyncReader OpenAsyncReader(
Stream stream,
ReaderOptions? options,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncReader)ArjReader.Open(stream, options);
return (IAsyncReader)ArjReader.OpenReader(stream, options);
}
public override ValueTask<bool> IsArchiveAsync(

View File

@@ -133,7 +133,7 @@ public abstract class Factory : IFactory
)
{
((IStreamStack)stream).StackSeek(pos);
return (true, readerFactory.OpenReaderAsync(stream, options, cancellationToken));
return (true, readerFactory.OpenAsyncReader(stream, options, cancellationToken));
}
}

View File

@@ -61,12 +61,12 @@ public class GZipFactory
#region IArchiveFactory
/// <inheritdoc/>
public IArchive Open(Stream stream, ReaderOptions? readerOptions = null) =>
GZipArchive.Open(stream, readerOptions);
public IArchive OpenArchive(Stream stream, ReaderOptions? readerOptions = null) =>
GZipArchive.OpenArchive(stream, readerOptions);
/// <inheritdoc/>
public IAsyncArchive OpenAsync(Stream stream, ReaderOptions? readerOptions = null) =>
(IAsyncArchive)Open(stream, readerOptions);
public IAsyncArchive OpenAsyncArchive(Stream stream, ReaderOptions? readerOptions = null) =>
(IAsyncArchive)OpenArchive(stream, readerOptions);
public override ValueTask<bool> IsArchiveAsync(
Stream stream,
@@ -75,14 +75,14 @@ public class GZipFactory
) => new(IsArchive(stream, password, bufferSize));
/// <inheritdoc/>
public IAsyncArchive OpenAsync(
public IAsyncArchive OpenAsyncArchive(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncArchive)Open(fileInfo, readerOptions);
return (IAsyncArchive)OpenArchive(fileInfo, readerOptions);
}
#endregion
@@ -90,28 +90,32 @@ public class GZipFactory
#region IMultiArchiveFactory
/// <inheritdoc/>
public IArchive Open(IReadOnlyList<Stream> streams, ReaderOptions? readerOptions = null) =>
GZipArchive.Open(streams, readerOptions);
/// <inheritdoc/>
public IAsyncArchive OpenAsync(
public IArchive OpenArchive(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null
) => (IAsyncArchive)Open(streams, readerOptions);
) => GZipArchive.OpenArchive(streams, readerOptions);
/// <inheritdoc/>
public IArchive Open(IReadOnlyList<FileInfo> fileInfos, ReaderOptions? readerOptions = null) =>
GZipArchive.Open(fileInfos, readerOptions);
public IAsyncArchive OpenAsyncArchive(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null
) => (IAsyncArchive)OpenArchive(streams, readerOptions);
/// <inheritdoc/>
public IAsyncArchive OpenAsync(
public IArchive OpenArchive(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null
) => GZipArchive.OpenArchive(fileInfos, readerOptions);
/// <inheritdoc/>
public IAsyncArchive OpenAsyncArchive(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncArchive)Open(fileInfos, readerOptions);
return (IAsyncArchive)OpenArchive(fileInfos, readerOptions);
}
#endregion
@@ -150,29 +154,29 @@ public class GZipFactory
/// <inheritdoc/>
public IReader OpenReader(Stream stream, ReaderOptions? options) =>
GZipReader.Open(stream, options);
GZipReader.OpenReader(stream, options);
/// <inheritdoc/>
public IAsyncReader OpenReaderAsync(
public IAsyncReader OpenAsyncReader(
Stream stream,
ReaderOptions? options,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncReader)GZipReader.Open(stream, options);
return (IAsyncReader)GZipReader.OpenReader(stream, options);
}
/// <inheritdoc/>
public IArchive Open(FileInfo fileInfo, ReaderOptions? readerOptions = null) =>
GZipArchive.Open(fileInfo, readerOptions);
public IArchive OpenArchive(FileInfo fileInfo, ReaderOptions? readerOptions = null) =>
GZipArchive.OpenArchive(fileInfo, readerOptions);
#endregion
#region IWriterFactory
/// <inheritdoc/>
public IWriter Open(Stream stream, WriterOptions writerOptions)
public IWriter OpenWriter(Stream stream, WriterOptions writerOptions)
{
if (writerOptions.CompressionType != CompressionType.GZip)
{
@@ -182,7 +186,7 @@ public class GZipFactory
}
/// <inheritdoc/>
public IAsyncWriter OpenAsync(
public IAsyncWriter OpenAsyncWriter(
Stream stream,
WriterOptions writerOptions,
CancellationToken cancellationToken = default
@@ -193,7 +197,7 @@ public class GZipFactory
{
throw new InvalidFormatException("GZip archives only support GZip compression type.");
}
return (IAsyncWriter)Open(stream, writerOptions);
return (IAsyncWriter)OpenWriter(stream, writerOptions);
}
#endregion
@@ -201,7 +205,7 @@ public class GZipFactory
#region IWriteableArchiveFactory
/// <inheritdoc/>
public IWritableArchive CreateWriteableArchive() => GZipArchive.Create();
public IWritableArchive CreateArchive() => GZipArchive.CreateArchive();
#endregion
}

View File

@@ -46,26 +46,26 @@ public class RarFactory : Factory, IArchiveFactory, IMultiArchiveFactory, IReade
#region IArchiveFactory
/// <inheritdoc/>
public IArchive Open(Stream stream, ReaderOptions? readerOptions = null) =>
RarArchive.Open(stream, readerOptions);
public IArchive OpenArchive(Stream stream, ReaderOptions? readerOptions = null) =>
RarArchive.OpenArchive(stream, readerOptions);
/// <inheritdoc/>
public IAsyncArchive OpenAsync(Stream stream, ReaderOptions? readerOptions = null) =>
(IAsyncArchive)Open(stream, readerOptions);
public IAsyncArchive OpenAsyncArchive(Stream stream, ReaderOptions? readerOptions = null) =>
(IAsyncArchive)OpenArchive(stream, readerOptions);
/// <inheritdoc/>
public IArchive Open(FileInfo fileInfo, ReaderOptions? readerOptions = null) =>
RarArchive.Open(fileInfo, readerOptions);
public IArchive OpenArchive(FileInfo fileInfo, ReaderOptions? readerOptions = null) =>
RarArchive.OpenArchive(fileInfo, readerOptions);
/// <inheritdoc/>
public IAsyncArchive OpenAsync(
public IAsyncArchive OpenAsyncArchive(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncArchive)Open(fileInfo, readerOptions);
return (IAsyncArchive)OpenArchive(fileInfo, readerOptions);
}
public override ValueTask<bool> IsArchiveAsync(
@@ -79,28 +79,32 @@ public class RarFactory : Factory, IArchiveFactory, IMultiArchiveFactory, IReade
#region IMultiArchiveFactory
/// <inheritdoc/>
public IArchive Open(IReadOnlyList<Stream> streams, ReaderOptions? readerOptions = null) =>
RarArchive.Open(streams, readerOptions);
/// <inheritdoc/>
public IAsyncArchive OpenAsync(
public IArchive OpenArchive(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null
) => (IAsyncArchive)Open(streams, readerOptions);
) => RarArchive.OpenArchive(streams, readerOptions);
/// <inheritdoc/>
public IArchive Open(IReadOnlyList<FileInfo> fileInfos, ReaderOptions? readerOptions = null) =>
RarArchive.Open(fileInfos, readerOptions);
public IAsyncArchive OpenAsyncArchive(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null
) => (IAsyncArchive)OpenArchive(streams, readerOptions);
/// <inheritdoc/>
public IAsyncArchive OpenAsync(
public IArchive OpenArchive(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null
) => RarArchive.OpenArchive(fileInfos, readerOptions);
/// <inheritdoc/>
public IAsyncArchive OpenAsyncArchive(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncArchive)Open(fileInfos, readerOptions);
return (IAsyncArchive)OpenArchive(fileInfos, readerOptions);
}
#endregion
@@ -109,17 +113,17 @@ public class RarFactory : Factory, IArchiveFactory, IMultiArchiveFactory, IReade
/// <inheritdoc/>
public IReader OpenReader(Stream stream, ReaderOptions? options) =>
RarReader.Open(stream, options);
RarReader.OpenReader(stream, options);
/// <inheritdoc/>
public IAsyncReader OpenReaderAsync(
public IAsyncReader OpenAsyncReader(
Stream stream,
ReaderOptions? options,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncReader)RarReader.Open(stream, options);
return (IAsyncReader)RarReader.OpenReader(stream, options);
}
#endregion

View File

@@ -41,26 +41,26 @@ public class SevenZipFactory : Factory, IArchiveFactory, IMultiArchiveFactory
#region IArchiveFactory
/// <inheritdoc/>
public IArchive Open(Stream stream, ReaderOptions? readerOptions = null) =>
SevenZipArchive.Open(stream, readerOptions);
public IArchive OpenArchive(Stream stream, ReaderOptions? readerOptions = null) =>
SevenZipArchive.OpenArchive(stream, readerOptions);
/// <inheritdoc/>
public IAsyncArchive OpenAsync(Stream stream, ReaderOptions? readerOptions = null) =>
(IAsyncArchive)Open(stream, readerOptions);
public IAsyncArchive OpenAsyncArchive(Stream stream, ReaderOptions? readerOptions = null) =>
(IAsyncArchive)OpenArchive(stream, readerOptions);
/// <inheritdoc/>
public IArchive Open(FileInfo fileInfo, ReaderOptions? readerOptions = null) =>
SevenZipArchive.Open(fileInfo, readerOptions);
public IArchive OpenArchive(FileInfo fileInfo, ReaderOptions? readerOptions = null) =>
SevenZipArchive.OpenArchive(fileInfo, readerOptions);
/// <inheritdoc/>
public IAsyncArchive OpenAsync(
public IAsyncArchive OpenAsyncArchive(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncArchive)Open(fileInfo, readerOptions);
return (IAsyncArchive)OpenArchive(fileInfo, readerOptions);
}
public override ValueTask<bool> IsArchiveAsync(
@@ -74,28 +74,32 @@ public class SevenZipFactory : Factory, IArchiveFactory, IMultiArchiveFactory
#region IMultiArchiveFactory
/// <inheritdoc/>
public IArchive Open(IReadOnlyList<Stream> streams, ReaderOptions? readerOptions = null) =>
SevenZipArchive.Open(streams, readerOptions);
/// <inheritdoc/>
public IAsyncArchive OpenAsync(
public IArchive OpenArchive(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null
) => (IAsyncArchive)Open(streams, readerOptions);
) => SevenZipArchive.OpenArchive(streams, readerOptions);
/// <inheritdoc/>
public IArchive Open(IReadOnlyList<FileInfo> fileInfos, ReaderOptions? readerOptions = null) =>
SevenZipArchive.Open(fileInfos, readerOptions);
public IAsyncArchive OpenAsyncArchive(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null
) => (IAsyncArchive)OpenArchive(streams, readerOptions);
/// <inheritdoc/>
public IAsyncArchive OpenAsync(
public IArchive OpenArchive(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null
) => SevenZipArchive.OpenArchive(fileInfos, readerOptions);
/// <inheritdoc/>
public IAsyncArchive OpenAsyncArchive(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncArchive)Open(fileInfos, readerOptions);
return (IAsyncArchive)OpenArchive(fileInfos, readerOptions);
}
#endregion

View File

@@ -72,26 +72,26 @@ public class TarFactory
#region IArchiveFactory
/// <inheritdoc/>
public IArchive Open(Stream stream, ReaderOptions? readerOptions = null) =>
TarArchive.Open(stream, readerOptions);
public IArchive OpenArchive(Stream stream, ReaderOptions? readerOptions = null) =>
TarArchive.OpenArchive(stream, readerOptions);
/// <inheritdoc/>
public IAsyncArchive OpenAsync(Stream stream, ReaderOptions? readerOptions = null) =>
(IAsyncArchive)Open(stream, readerOptions);
public IAsyncArchive OpenAsyncArchive(Stream stream, ReaderOptions? readerOptions = null) =>
(IAsyncArchive)OpenArchive(stream, readerOptions);
/// <inheritdoc/>
public IArchive Open(FileInfo fileInfo, ReaderOptions? readerOptions = null) =>
TarArchive.Open(fileInfo, readerOptions);
public IArchive OpenArchive(FileInfo fileInfo, ReaderOptions? readerOptions = null) =>
TarArchive.OpenArchive(fileInfo, readerOptions);
/// <inheritdoc/>
public IAsyncArchive OpenAsync(
public IAsyncArchive OpenAsyncArchive(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncArchive)Open(fileInfo, readerOptions);
return (IAsyncArchive)OpenArchive(fileInfo, readerOptions);
}
#endregion
@@ -99,28 +99,32 @@ public class TarFactory
#region IMultiArchiveFactory
/// <inheritdoc/>
public IArchive Open(IReadOnlyList<Stream> streams, ReaderOptions? readerOptions = null) =>
TarArchive.Open(streams, readerOptions);
/// <inheritdoc/>
public IAsyncArchive OpenAsync(
public IArchive OpenArchive(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null
) => (IAsyncArchive)Open(streams, readerOptions);
) => TarArchive.OpenArchive(streams, readerOptions);
/// <inheritdoc/>
public IArchive Open(IReadOnlyList<FileInfo> fileInfos, ReaderOptions? readerOptions = null) =>
TarArchive.Open(fileInfos, readerOptions);
public IAsyncArchive OpenAsyncArchive(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null
) => (IAsyncArchive)OpenArchive(streams, readerOptions);
/// <inheritdoc/>
public IAsyncArchive OpenAsync(
public IArchive OpenArchive(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null
) => TarArchive.OpenArchive(fileInfos, readerOptions);
/// <inheritdoc/>
public IAsyncArchive OpenAsyncArchive(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncArchive)Open(fileInfos, readerOptions);
return (IAsyncArchive)OpenArchive(fileInfos, readerOptions);
}
#endregion
@@ -272,17 +276,17 @@ public class TarFactory
/// <inheritdoc/>
public IReader OpenReader(Stream stream, ReaderOptions? options) =>
TarReader.Open(stream, options);
TarReader.OpenReader(stream, options);
/// <inheritdoc/>
public IAsyncReader OpenReaderAsync(
public IAsyncReader OpenAsyncReader(
Stream stream,
ReaderOptions? options,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncReader)TarReader.Open(stream, options);
return (IAsyncReader)TarReader.OpenReader(stream, options);
}
#endregion
@@ -290,18 +294,18 @@ public class TarFactory
#region IWriterFactory
/// <inheritdoc/>
public IWriter Open(Stream stream, WriterOptions writerOptions) =>
public IWriter OpenWriter(Stream stream, WriterOptions writerOptions) =>
new TarWriter(stream, new TarWriterOptions(writerOptions));
/// <inheritdoc/>
public IAsyncWriter OpenAsync(
public IAsyncWriter OpenAsyncWriter(
Stream stream,
WriterOptions writerOptions,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncWriter)Open(stream, writerOptions);
return (IAsyncWriter)OpenWriter(stream, writerOptions);
}
#endregion
@@ -309,7 +313,7 @@ public class TarFactory
#region IWriteableArchiveFactory
/// <inheritdoc/>
public IWritableArchive CreateWriteableArchive() => TarArchive.Create();
public IWritableArchive CreateArchive() => TarArchive.CreateArchive();
#endregion
}

View File

@@ -139,26 +139,26 @@ public class ZipFactory
#region IArchiveFactory
/// <inheritdoc/>
public IArchive Open(Stream stream, ReaderOptions? readerOptions = null) =>
ZipArchive.Open(stream, readerOptions);
public IArchive OpenArchive(Stream stream, ReaderOptions? readerOptions = null) =>
ZipArchive.OpenArchive(stream, readerOptions);
/// <inheritdoc/>
public IAsyncArchive OpenAsync(Stream stream, ReaderOptions? readerOptions = null) =>
(IAsyncArchive)Open(stream, readerOptions);
public IAsyncArchive OpenAsyncArchive(Stream stream, ReaderOptions? readerOptions = null) =>
(IAsyncArchive)OpenArchive(stream, readerOptions);
/// <inheritdoc/>
public IArchive Open(FileInfo fileInfo, ReaderOptions? readerOptions = null) =>
ZipArchive.Open(fileInfo, readerOptions);
public IArchive OpenArchive(FileInfo fileInfo, ReaderOptions? readerOptions = null) =>
ZipArchive.OpenArchive(fileInfo, readerOptions);
/// <inheritdoc/>
public IAsyncArchive OpenAsync(
public IAsyncArchive OpenAsyncArchive(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncArchive)Open(fileInfo, readerOptions);
return (IAsyncArchive)OpenArchive(fileInfo, readerOptions);
}
#endregion
@@ -166,28 +166,32 @@ public class ZipFactory
#region IMultiArchiveFactory
/// <inheritdoc/>
public IArchive Open(IReadOnlyList<Stream> streams, ReaderOptions? readerOptions = null) =>
ZipArchive.Open(streams, readerOptions);
/// <inheritdoc/>
public IAsyncArchive OpenAsync(
public IArchive OpenArchive(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null
) => (IAsyncArchive)Open(streams, readerOptions);
) => ZipArchive.OpenArchive(streams, readerOptions);
/// <inheritdoc/>
public IArchive Open(IReadOnlyList<FileInfo> fileInfos, ReaderOptions? readerOptions = null) =>
ZipArchive.Open(fileInfos, readerOptions);
public IAsyncArchive OpenAsyncArchive(
IReadOnlyList<Stream> streams,
ReaderOptions? readerOptions = null
) => (IAsyncArchive)OpenArchive(streams, readerOptions);
/// <inheritdoc/>
public IAsyncArchive OpenAsync(
public IArchive OpenArchive(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null
) => ZipArchive.OpenArchive(fileInfos, readerOptions);
/// <inheritdoc/>
public IAsyncArchive OpenAsyncArchive(
IReadOnlyList<FileInfo> fileInfos,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncArchive)Open(fileInfos, readerOptions);
return (IAsyncArchive)OpenArchive(fileInfos, readerOptions);
}
#endregion
@@ -196,17 +200,17 @@ public class ZipFactory
/// <inheritdoc/>
public IReader OpenReader(Stream stream, ReaderOptions? options) =>
ZipReader.Open(stream, options);
ZipReader.OpenReader(stream, options);
/// <inheritdoc/>
public IAsyncReader OpenReaderAsync(
public IAsyncReader OpenAsyncReader(
Stream stream,
ReaderOptions? options,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncReader)ZipReader.Open(stream, options);
return (IAsyncReader)ZipReader.OpenReader(stream, options);
}
#endregion
@@ -214,18 +218,18 @@ public class ZipFactory
#region IWriterFactory
/// <inheritdoc/>
public IWriter Open(Stream stream, WriterOptions writerOptions) =>
public IWriter OpenWriter(Stream stream, WriterOptions writerOptions) =>
new ZipWriter(stream, new ZipWriterOptions(writerOptions));
/// <inheritdoc/>
public IAsyncWriter OpenAsync(
public IAsyncWriter OpenAsyncWriter(
Stream stream,
WriterOptions writerOptions,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncWriter)Open(stream, writerOptions);
return (IAsyncWriter)OpenWriter(stream, writerOptions);
}
#endregion
@@ -233,7 +237,7 @@ public class ZipFactory
#region IWriteableArchiveFactory
/// <inheritdoc/>
public IWritableArchive CreateWriteableArchive() => ZipArchive.Create();
public IWritableArchive CreateArchive() => ZipArchive.CreateArchive();
#endregion
}

View File

@@ -38,7 +38,7 @@ internal class BufferedSubStream : SharpCompressStream, IStreamStack
private int _cacheOffset;
private int _cacheLength;
private readonly byte[] _cache = ArrayPool<byte>.Shared.Rent(32 << 10);
private readonly byte[] _cache = ArrayPool<byte>.Shared.Rent(32 << 10);
private long origin;
private long BytesLeftToRead { get; set; }
@@ -154,7 +154,7 @@ internal class BufferedSubStream : SharpCompressStream, IStreamStack
return count;
}
#if !NETFRAMEWORK && !NETSTANDARD2_0
#if !LEGACY_DOTNET
public override async ValueTask<int> ReadAsync(
Memory<byte> buffer,
CancellationToken cancellationToken = default

View File

@@ -64,7 +64,7 @@ internal sealed class ProgressReportingStream : Stream
return bytesRead;
}
#if !NETFRAMEWORK && !NETSTANDARD2_0
#if !LEGACY_DOTNET
public override int Read(Span<byte> buffer)
{
var bytesRead = _baseStream.Read(buffer);
@@ -95,7 +95,7 @@ internal sealed class ProgressReportingStream : Stream
return bytesRead;
}
#if !NETFRAMEWORK && !NETSTANDARD2_0
#if !LEGACY_DOTNET
public override async ValueTask<int> ReadAsync(
Memory<byte> buffer,
CancellationToken cancellationToken = default
@@ -147,7 +147,7 @@ internal sealed class ProgressReportingStream : Stream
base.Dispose(disposing);
}
#if !NETFRAMEWORK && !NETSTANDARD2_0
#if !LEGACY_DOTNET
public override async ValueTask DisposeAsync()
{
if (!_leaveOpen)

View File

@@ -81,7 +81,7 @@ internal class ReadOnlySubStream : SharpCompressStream, IStreamStack
return value;
}
#if !NETFRAMEWORK && !NETSTANDARD2_0
#if !LEGACY_DOTNET
public override int Read(Span<byte> buffer)
{
var sliceLen = BytesLeftToRead < buffer.Length ? BytesLeftToRead : buffer.Length;
@@ -117,7 +117,7 @@ internal class ReadOnlySubStream : SharpCompressStream, IStreamStack
return read;
}
#if !NETFRAMEWORK && !NETSTANDARD2_0
#if !LEGACY_DOTNET
public override async ValueTask<int> ReadAsync(
Memory<byte> buffer,
CancellationToken cancellationToken = default

View File

@@ -384,7 +384,7 @@ public class SharpCompressStream : Stream, IStreamStack
await Stream.FlushAsync(cancellationToken).ConfigureAwait(false);
}
#if !NETFRAMEWORK && !NETSTANDARD2_0
#if !LEGACY_DOTNET
public override async ValueTask<int> ReadAsync(
Memory<byte> buffer,

View File

@@ -98,6 +98,30 @@ public class SourceStream : Stream, IStreamStack
private Stream Current => _streams[_stream];
/// <summary>
/// Creates an independent stream for the specified volume index.
/// This allows multiple threads to read from different positions concurrently.
/// Only works when IsFileMode is true.
/// </summary>
/// <param name="volumeIndex">The volume index to create a stream for</param>
/// <returns>A new independent FileStream, or null if not in file mode or volume doesn't exist</returns>
public Stream? CreateIndependentStream(int volumeIndex)
{
if (!IsFileMode)
{
return null;
}
// Ensure the volume is loaded
if (!LoadStream(volumeIndex))
{
return null;
}
// Create a new independent stream from the FileInfo
return _files[volumeIndex].OpenRead();
}
public bool LoadStream(int index) //ensure all parts to id are loaded
{
while (_streams.Count <= index)
@@ -289,7 +313,7 @@ public class SourceStream : Stream, IStreamStack
return total - count;
}
#if !NETFRAMEWORK && !NETSTANDARD2_0
#if !LEGACY_DOTNET
public override async ValueTask<int> ReadAsync(
Memory<byte> buffer,

View File

@@ -21,7 +21,7 @@ internal static class NotNullExtensions
return source.AsEnumerable();
}
#if NETFRAMEWORK || NETSTANDARD
#if LEGACY_DOTNET
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T NotNull<T>(this T? obj, string? message = null)
where T : class

View File

@@ -1,4 +1,4 @@
#if NETFRAMEWORK || NETSTANDARD2_0
#if LEGACY_DOTNET
namespace SharpCompress;

View File

@@ -277,7 +277,7 @@ public abstract class AbstractReader<TEntry, TVolume> : IReader, IAsyncReader
}
}
//don't know the size so we have to try to decompress to skip
#if NETFRAMEWORK || NETSTANDARD2_0
#if LEGACY_DOTNET
using var s = await OpenEntryStreamAsync(cancellationToken).ConfigureAwait(false);
await s.SkipEntryAsync(cancellationToken).ConfigureAwait(false);
#else
@@ -344,7 +344,7 @@ public abstract class AbstractReader<TEntry, TVolume> : IReader, IAsyncReader
internal async ValueTask WriteAsync(Stream writeStream, CancellationToken cancellationToken)
{
#if NETFRAMEWORK || NETSTANDARD2_0
#if LEGACY_DOTNET
using Stream s = await OpenEntryStreamAsync(cancellationToken).ConfigureAwait(false);
var sourceStream = WrapWithProgress(s, Entry);
await sourceStream.CopyToAsync(writeStream, 81920, cancellationToken).ConfigureAwait(false);

View File

@@ -7,7 +7,7 @@ namespace SharpCompress.Readers.Ace;
public partial class AceReader : IReaderOpenable
{
public static IAsyncReader OpenAsync(
public static IAsyncReader OpenAsyncReader(
string path,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
@@ -15,39 +15,39 @@ public partial class AceReader : IReaderOpenable
{
cancellationToken.ThrowIfCancellationRequested();
path.NotNullOrEmpty(nameof(path));
return (IAsyncReader)Open(new FileInfo(path), readerOptions);
return (IAsyncReader)OpenReader(new FileInfo(path), readerOptions);
}
public static IAsyncReader OpenAsync(
public static IAsyncReader OpenAsyncReader(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncReader)Open(stream, readerOptions);
return (IAsyncReader)OpenReader(stream, readerOptions);
}
public static IAsyncReader OpenAsync(
public static IAsyncReader OpenAsyncReader(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncReader)Open(fileInfo, readerOptions);
return (IAsyncReader)OpenReader(fileInfo, readerOptions);
}
public static IReader Open(string filePath, ReaderOptions? readerOptions = null)
public static IReader OpenReader(string filePath, ReaderOptions? readerOptions = null)
{
filePath.NotNullOrEmpty(nameof(filePath));
return Open(new FileInfo(filePath), readerOptions);
return OpenReader(new FileInfo(filePath), readerOptions);
}
public static IReader Open(FileInfo fileInfo, ReaderOptions? readerOptions = null)
public static IReader OpenReader(FileInfo fileInfo, ReaderOptions? readerOptions = null)
{
fileInfo.NotNull(nameof(fileInfo));
return Open(fileInfo.OpenRead(), readerOptions);
return OpenReader(fileInfo.OpenRead(), readerOptions);
}
}
#endif

View File

@@ -50,7 +50,7 @@ namespace SharpCompress.Readers.Ace
/// <param name="stream">The stream containing the ACE archive.</param>
/// <param name="options">Reader options.</param>
/// <returns>An AceReader instance.</returns>
public static IReader Open(Stream stream, ReaderOptions? options = null)
public static IReader OpenReader(Stream stream, ReaderOptions? options = null)
{
stream.NotNull(nameof(stream));
return new SingleVolumeAceReader(stream, options ?? new ReaderOptions());
@@ -62,7 +62,7 @@ namespace SharpCompress.Readers.Ace
/// <param name="streams"></param>
/// <param name="options"></param>
/// <returns></returns>
public static IReader Open(IEnumerable<Stream> streams, ReaderOptions? options = null)
public static IReader OpenReader(IEnumerable<Stream> streams, ReaderOptions? options = null)
{
streams.NotNull(nameof(streams));
return new MultiVolumeAceReader(streams, options ?? new ReaderOptions());

View File

@@ -7,7 +7,7 @@ namespace SharpCompress.Readers.Arc;
public partial class ArcReader : IReaderOpenable
{
public static IAsyncReader OpenAsync(
public static IAsyncReader OpenAsyncReader(
string path,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
@@ -15,39 +15,39 @@ public partial class ArcReader : IReaderOpenable
{
cancellationToken.ThrowIfCancellationRequested();
path.NotNullOrEmpty(nameof(path));
return (IAsyncReader)Open(new FileInfo(path), readerOptions);
return (IAsyncReader)OpenReader(new FileInfo(path), readerOptions);
}
public static IAsyncReader OpenAsync(
public static IAsyncReader OpenAsyncReader(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncReader)Open(stream, readerOptions);
return (IAsyncReader)OpenReader(stream, readerOptions);
}
public static IAsyncReader OpenAsync(
public static IAsyncReader OpenAsyncReader(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncReader)Open(fileInfo, readerOptions);
return (IAsyncReader)OpenReader(fileInfo, readerOptions);
}
public static IReader Open(string filePath, ReaderOptions? readerOptions = null)
public static IReader OpenReader(string filePath, ReaderOptions? readerOptions = null)
{
filePath.NotNullOrEmpty(nameof(filePath));
return Open(new FileInfo(filePath), readerOptions);
return OpenReader(new FileInfo(filePath), readerOptions);
}
public static IReader Open(FileInfo fileInfo, ReaderOptions? readerOptions = null)
public static IReader OpenReader(FileInfo fileInfo, ReaderOptions? readerOptions = null)
{
fileInfo.NotNull(nameof(fileInfo));
return Open(fileInfo.OpenRead(), readerOptions);
return OpenReader(fileInfo.OpenRead(), readerOptions);
}
}
#endif

View File

@@ -22,7 +22,7 @@ namespace SharpCompress.Readers.Arc
/// <param name="stream"></param>
/// <param name="options"></param>
/// <returns></returns>
public static IReader Open(Stream stream, ReaderOptions? options = null)
public static IReader OpenReader(Stream stream, ReaderOptions? options = null)
{
stream.NotNull(nameof(stream));
return new ArcReader(stream, options ?? new ReaderOptions());

View File

@@ -7,7 +7,7 @@ namespace SharpCompress.Readers.Arj;
public partial class ArjReader : IReaderOpenable
{
public static IAsyncReader OpenAsync(
public static IAsyncReader OpenAsyncReader(
string path,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
@@ -15,39 +15,39 @@ public partial class ArjReader : IReaderOpenable
{
cancellationToken.ThrowIfCancellationRequested();
path.NotNullOrEmpty(nameof(path));
return (IAsyncReader)Open(new FileInfo(path), readerOptions);
return (IAsyncReader)OpenReader(new FileInfo(path), readerOptions);
}
public static IAsyncReader OpenAsync(
public static IAsyncReader OpenAsyncReader(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncReader)Open(stream, readerOptions);
return (IAsyncReader)OpenReader(stream, readerOptions);
}
public static IAsyncReader OpenAsync(
public static IAsyncReader OpenAsyncReader(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncReader)Open(fileInfo, readerOptions);
return (IAsyncReader)OpenReader(fileInfo, readerOptions);
}
public static IReader Open(string filePath, ReaderOptions? readerOptions = null)
public static IReader OpenReader(string filePath, ReaderOptions? readerOptions = null)
{
filePath.NotNullOrEmpty(nameof(filePath));
return Open(new FileInfo(filePath), readerOptions);
return OpenReader(new FileInfo(filePath), readerOptions);
}
public static IReader Open(FileInfo fileInfo, ReaderOptions? readerOptions = null)
public static IReader OpenReader(FileInfo fileInfo, ReaderOptions? readerOptions = null)
{
fileInfo.NotNull(nameof(fileInfo));
return Open(fileInfo.OpenRead(), readerOptions);
return OpenReader(fileInfo.OpenRead(), readerOptions);
}
}
#endif

View File

@@ -27,7 +27,7 @@ namespace SharpCompress.Readers.Arj
/// <param name="stream"></param>
/// <param name="options"></param>
/// <returns></returns>
public static IReader Open(Stream stream, ReaderOptions? options = null)
public static IReader OpenReader(Stream stream, ReaderOptions? options = null)
{
stream.NotNull(nameof(stream));
return new SingleVolumeArjReader(stream, options ?? new ReaderOptions());
@@ -39,7 +39,7 @@ namespace SharpCompress.Readers.Arj
/// <param name="streams"></param>
/// <param name="options"></param>
/// <returns></returns>
public static IReader Open(IEnumerable<Stream> streams, ReaderOptions? options = null)
public static IReader OpenReader(IEnumerable<Stream> streams, ReaderOptions? options = null)
{
streams.NotNull(nameof(streams));
return new MultiVolumeArjReader(streams, options ?? new ReaderOptions());

View File

@@ -7,7 +7,7 @@ namespace SharpCompress.Readers.GZip;
public partial class GZipReader : IReaderOpenable
{
public static IAsyncReader OpenAsync(
public static IAsyncReader OpenAsyncReader(
string path,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
@@ -15,39 +15,39 @@ public partial class GZipReader : IReaderOpenable
{
cancellationToken.ThrowIfCancellationRequested();
path.NotNullOrEmpty(nameof(path));
return (IAsyncReader)Open(new FileInfo(path), readerOptions);
return (IAsyncReader)OpenReader(new FileInfo(path), readerOptions);
}
public static IAsyncReader OpenAsync(
public static IAsyncReader OpenAsyncReader(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncReader)Open(stream, readerOptions);
return (IAsyncReader)OpenReader(stream, readerOptions);
}
public static IAsyncReader OpenAsync(
public static IAsyncReader OpenAsyncReader(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncReader)Open(fileInfo, readerOptions);
return (IAsyncReader)OpenReader(fileInfo, readerOptions);
}
public static IReader Open(string filePath, ReaderOptions? readerOptions = null)
public static IReader OpenReader(string filePath, ReaderOptions? readerOptions = null)
{
filePath.NotNullOrEmpty(nameof(filePath));
return Open(new FileInfo(filePath), readerOptions);
return OpenReader(new FileInfo(filePath), readerOptions);
}
public static IReader Open(FileInfo fileInfo, ReaderOptions? readerOptions = null)
public static IReader OpenReader(FileInfo fileInfo, ReaderOptions? readerOptions = null)
{
fileInfo.NotNull(nameof(fileInfo));
return Open(fileInfo.OpenRead(), readerOptions);
return OpenReader(fileInfo.OpenRead(), readerOptions);
}
}
#endif

View File

@@ -12,7 +12,7 @@ public partial class GZipReader : AbstractReader<GZipEntry, GZipVolume>
public override GZipVolume Volume { get; }
#region Open
#region OpenReader
/// <summary>
/// Opens a GZipReader for Non-seeking usage with a single volume
@@ -20,13 +20,13 @@ public partial class GZipReader : AbstractReader<GZipEntry, GZipVolume>
/// <param name="stream"></param>
/// <param name="options"></param>
/// <returns></returns>
public static IReader Open(Stream stream, ReaderOptions? options = null)
public static IReader OpenReader(Stream stream, ReaderOptions? options = null)
{
stream.NotNull(nameof(stream));
return new GZipReader(stream, options ?? new ReaderOptions());
}
#endregion Open
#endregion OpenReader
protected override IEnumerable<GZipEntry> GetEntries(Stream stream) =>
GZipEntry.GetEntries(stream, Options);

View File

@@ -6,13 +6,21 @@ namespace SharpCompress.Readers;
public interface IReaderFactory : Factories.IFactory
{
/// <summary>
/// Opens a Reader for Non-seeking usage
/// Opens a Reader for Non-seeking usage.
/// </summary>
/// <param name="stream"></param>
/// <param name="options"></param>
/// <returns></returns>
IReader OpenReader(Stream stream, ReaderOptions? options);
IAsyncReader OpenReaderAsync(
/// <summary>
/// Opens a Reader for Non-seeking usage asynchronously.
/// </summary>
/// <param name="stream"></param>
/// <param name="options"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
IAsyncReader OpenAsyncReader(
Stream stream,
ReaderOptions? options,
CancellationToken cancellationToken

View File

@@ -6,25 +6,28 @@ namespace SharpCompress.Readers;
public interface IReaderOpenable
{
public static abstract IReader Open(string filePath, ReaderOptions? readerOptions = null);
public static abstract IReader OpenReader(string filePath, ReaderOptions? readerOptions = null);
public static abstract IReader Open(FileInfo fileInfo, ReaderOptions? readerOptions = null);
public static abstract IReader OpenReader(
FileInfo fileInfo,
ReaderOptions? readerOptions = null
);
public static abstract IReader Open(Stream stream, ReaderOptions? readerOptions = null);
public static abstract IReader OpenReader(Stream stream, ReaderOptions? readerOptions = null);
public static abstract IAsyncReader OpenAsync(
public static abstract IAsyncReader OpenAsyncReader(
string path,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
);
public static abstract IAsyncReader OpenAsync(
public static abstract IAsyncReader OpenAsyncReader(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
);
public static abstract IAsyncReader OpenAsync(
public static abstract IAsyncReader OpenAsyncReader(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default

View File

@@ -7,7 +7,7 @@ namespace SharpCompress.Readers.Rar;
public partial class RarReader : IReaderOpenable
{
public static IAsyncReader OpenAsync(
public static IAsyncReader OpenAsyncReader(
string path,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
@@ -15,27 +15,27 @@ public partial class RarReader : IReaderOpenable
{
cancellationToken.ThrowIfCancellationRequested();
path.NotNullOrEmpty(nameof(path));
return (IAsyncReader)Open(new FileInfo(path), readerOptions);
return (IAsyncReader)OpenReader(new FileInfo(path), readerOptions);
}
public static IAsyncReader OpenAsync(
public static IAsyncReader OpenAsyncReader(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncReader)Open(stream, readerOptions);
return (IAsyncReader)OpenReader(stream, readerOptions);
}
public static IAsyncReader OpenAsync(
public static IAsyncReader OpenAsyncReader(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncReader)Open(fileInfo, readerOptions);
return (IAsyncReader)OpenReader(fileInfo, readerOptions);
}
}
#endif

View File

@@ -40,27 +40,27 @@ public abstract partial class RarReader : AbstractReader<RarReaderEntry, RarVolu
public override RarVolume? Volume => volume;
public static IReader Open(string filePath, ReaderOptions? options = null)
public static IReader OpenReader(string filePath, ReaderOptions? options = null)
{
filePath.NotNullOrEmpty(nameof(filePath));
return Open(new FileInfo(filePath), options);
return OpenReader(new FileInfo(filePath), options);
}
public static IReader Open(FileInfo fileInfo, ReaderOptions? options = null)
public static IReader OpenReader(FileInfo fileInfo, ReaderOptions? options = null)
{
options ??= new ReaderOptions { LeaveStreamOpen = false };
return Open(fileInfo.OpenRead(), options);
return OpenReader(fileInfo.OpenRead(), options);
}
public static IReader Open(IEnumerable<string> filePaths, ReaderOptions? options = null)
public static IReader OpenReader(IEnumerable<string> filePaths, ReaderOptions? options = null)
{
return Open(filePaths.Select(x => new FileInfo(x)), options);
return OpenReader(filePaths.Select(x => new FileInfo(x)), options);
}
public static IReader Open(IEnumerable<FileInfo> fileInfos, ReaderOptions? options = null)
public static IReader OpenReader(IEnumerable<FileInfo> fileInfos, ReaderOptions? options = null)
{
options ??= new ReaderOptions { LeaveStreamOpen = false };
return Open(fileInfos.Select(x => x.OpenRead()), options);
return OpenReader(fileInfos.Select(x => x.OpenRead()), options);
}
/// <summary>
@@ -69,7 +69,7 @@ public abstract partial class RarReader : AbstractReader<RarReaderEntry, RarVolu
/// <param name="stream"></param>
/// <param name="options"></param>
/// <returns></returns>
public static IReader Open(Stream stream, ReaderOptions? options = null)
public static IReader OpenReader(Stream stream, ReaderOptions? options = null)
{
stream.NotNull(nameof(stream));
return new SingleVolumeRarReader(stream, options ?? new ReaderOptions());
@@ -81,7 +81,7 @@ public abstract partial class RarReader : AbstractReader<RarReaderEntry, RarVolu
/// <param name="streams"></param>
/// <param name="options"></param>
/// <returns></returns>
public static IReader Open(IEnumerable<Stream> streams, ReaderOptions? options = null)
public static IReader OpenReader(IEnumerable<Stream> streams, ReaderOptions? options = null)
{
streams.NotNull(nameof(streams));
return new MultiVolumeRarReader(streams, options ?? new ReaderOptions());

View File

@@ -11,10 +11,10 @@ namespace SharpCompress.Readers;
public static class ReaderFactory
{
public static IReader Open(string filePath, ReaderOptions? options = null)
public static IReader OpenReader(string filePath, ReaderOptions? options = null)
{
filePath.NotNullOrEmpty(nameof(filePath));
return Open(new FileInfo(filePath), options);
return OpenReader(new FileInfo(filePath), options);
}
/// <summary>
@@ -24,20 +24,20 @@ public static class ReaderFactory
/// <param name="options"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static IAsyncReader OpenAsync(
public static IAsyncReader OpenAsyncReader(
string filePath,
ReaderOptions? options = null,
CancellationToken cancellationToken = default
)
{
filePath.NotNullOrEmpty(nameof(filePath));
return OpenAsync(new FileInfo(filePath), options, cancellationToken);
return OpenAsyncReader(new FileInfo(filePath), options, cancellationToken);
}
public static IReader Open(FileInfo fileInfo, ReaderOptions? options = null)
public static IReader OpenReader(FileInfo fileInfo, ReaderOptions? options = null)
{
options ??= new ReaderOptions { LeaveStreamOpen = false };
return Open(fileInfo.OpenRead(), options);
return OpenReader(fileInfo.OpenRead(), options);
}
/// <summary>
@@ -47,14 +47,14 @@ public static class ReaderFactory
/// <param name="options"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static IAsyncReader OpenAsync(
public static IAsyncReader OpenAsyncReader(
FileInfo fileInfo,
ReaderOptions? options = null,
CancellationToken cancellationToken = default
)
{
options ??= new ReaderOptions { LeaveStreamOpen = false };
return OpenAsync(fileInfo.OpenRead(), options, cancellationToken);
return OpenAsyncReader(fileInfo.OpenRead(), options, cancellationToken);
}
/// <summary>
@@ -63,7 +63,7 @@ public static class ReaderFactory
/// <param name="stream"></param>
/// <param name="options"></param>
/// <returns></returns>
public static IReader Open(Stream stream, ReaderOptions? options = null)
public static IReader OpenReader(Stream stream, ReaderOptions? options = null)
{
stream.NotNull(nameof(stream));
options ??= new ReaderOptions() { LeaveStreamOpen = false };
@@ -110,7 +110,7 @@ public static class ReaderFactory
);
}
public static IAsyncReader OpenAsync(
public static IAsyncReader OpenAsyncReader(
Stream stream,
ReaderOptions? options = null,
CancellationToken cancellationToken = default
@@ -139,7 +139,7 @@ public static class ReaderFactory
if (testedFactory.IsArchive(bStream))
{
((IStreamStack)bStream).StackSeek(pos);
return readerFactory.OpenReaderAsync(bStream, options, cancellationToken);
return readerFactory.OpenAsyncReader(bStream, options, cancellationToken);
}
}
((IStreamStack)bStream).StackSeek(pos);
@@ -155,7 +155,7 @@ public static class ReaderFactory
if (factory is IReaderFactory readerFactory && factory.IsArchive(bStream))
{
((IStreamStack)bStream).StackSeek(pos);
return readerFactory.OpenReaderAsync(bStream, options, cancellationToken);
return readerFactory.OpenAsyncReader(bStream, options, cancellationToken);
}
}

View File

@@ -28,4 +28,12 @@ public class ReaderOptions : OptionsBase
/// When set, progress updates will be reported as entries are extracted.
/// </summary>
public IProgress<ProgressReport>? Progress { get; set; }
/// <summary>
/// Enable multi-threaded extraction support when the archive is opened from a FileInfo or file path.
/// When enabled, multiple threads can extract different entries concurrently by creating
/// independent file streams. This is only effective for archives opened from files, not streams.
/// Default is false for backward compatibility.
/// </summary>
public bool EnableMultiThreadedExtraction { get; set; }
}

View File

@@ -7,7 +7,7 @@ namespace SharpCompress.Readers.Tar;
public partial class TarReader : IReaderOpenable
{
public static IAsyncReader OpenAsync(
public static IAsyncReader OpenAsyncReader(
string path,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
@@ -15,39 +15,39 @@ public partial class TarReader : IReaderOpenable
{
cancellationToken.ThrowIfCancellationRequested();
path.NotNullOrEmpty(nameof(path));
return (IAsyncReader)Open(new FileInfo(path), readerOptions);
return (IAsyncReader)OpenReader(new FileInfo(path), readerOptions);
}
public static IAsyncReader OpenAsync(
public static IAsyncReader OpenAsyncReader(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncReader)Open(stream, readerOptions);
return (IAsyncReader)OpenReader(stream, readerOptions);
}
public static IAsyncReader OpenAsync(
public static IAsyncReader OpenAsyncReader(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncReader)Open(fileInfo, readerOptions);
return (IAsyncReader)OpenReader(fileInfo, readerOptions);
}
public static IReader Open(string filePath, ReaderOptions? readerOptions = null)
public static IReader OpenReader(string filePath, ReaderOptions? readerOptions = null)
{
filePath.NotNullOrEmpty(nameof(filePath));
return Open(new FileInfo(filePath), readerOptions);
return OpenReader(new FileInfo(filePath), readerOptions);
}
public static IReader Open(FileInfo fileInfo, ReaderOptions? readerOptions = null)
public static IReader OpenReader(FileInfo fileInfo, ReaderOptions? readerOptions = null)
{
fileInfo.NotNull(nameof(fileInfo));
return Open(fileInfo.OpenRead(), readerOptions);
return OpenReader(fileInfo.OpenRead(), readerOptions);
}
}
#endif

View File

@@ -45,7 +45,7 @@ public partial class TarReader : AbstractReader<TarEntry, TarVolume>
};
}
#region Open
#region OpenReader
/// <summary>
/// Opens a TarReader for Non-seeking usage with a single volume
@@ -53,7 +53,7 @@ public partial class TarReader : AbstractReader<TarEntry, TarVolume>
/// <param name="stream"></param>
/// <param name="options"></param>
/// <returns></returns>
public static IReader Open(Stream stream, ReaderOptions? options = null)
public static IReader OpenReader(Stream stream, ReaderOptions? options = null)
{
stream.NotNull(nameof(stream));
options = options ?? new ReaderOptions();
@@ -115,7 +115,7 @@ public partial class TarReader : AbstractReader<TarEntry, TarVolume>
return new TarReader(rewindableStream, options, CompressionType.None);
}
#endregion Open
#endregion OpenReader
protected override IEnumerable<TarEntry> GetEntries(Stream stream) =>
TarEntry.GetEntries(

View File

@@ -7,7 +7,7 @@ namespace SharpCompress.Readers.Zip;
public partial class ZipReader : IReaderOpenable
{
public static IAsyncReader OpenAsync(
public static IAsyncReader OpenAsyncReader(
string path,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
@@ -15,39 +15,39 @@ public partial class ZipReader : IReaderOpenable
{
cancellationToken.ThrowIfCancellationRequested();
path.NotNullOrEmpty(nameof(path));
return (IAsyncReader)Open(new FileInfo(path), readerOptions);
return (IAsyncReader)OpenReader(new FileInfo(path), readerOptions);
}
public static IAsyncReader OpenAsync(
public static IAsyncReader OpenAsyncReader(
Stream stream,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncReader)Open(stream, readerOptions);
return (IAsyncReader)OpenReader(stream, readerOptions);
}
public static IAsyncReader OpenAsync(
public static IAsyncReader OpenAsyncReader(
FileInfo fileInfo,
ReaderOptions? readerOptions = null,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncReader)Open(fileInfo, readerOptions);
return (IAsyncReader)OpenReader(fileInfo, readerOptions);
}
public static IReader Open(string filePath, ReaderOptions? readerOptions = null)
public static IReader OpenReader(string filePath, ReaderOptions? readerOptions = null)
{
filePath.NotNullOrEmpty(nameof(filePath));
return Open(new FileInfo(filePath), readerOptions);
return OpenReader(new FileInfo(filePath), readerOptions);
}
public static IReader Open(FileInfo fileInfo, ReaderOptions? readerOptions = null)
public static IReader OpenReader(FileInfo fileInfo, ReaderOptions? readerOptions = null)
{
fileInfo.NotNull(nameof(fileInfo));
return Open(fileInfo.OpenRead(), readerOptions);
return OpenReader(fileInfo.OpenRead(), readerOptions);
}
}
#endif

View File

@@ -45,13 +45,17 @@ public partial class ZipReader : AbstractReader<ZipEntry, ZipVolume>
/// <param name="stream"></param>
/// <param name="options"></param>
/// <returns></returns>
public static IReader Open(Stream stream, ReaderOptions? options = null)
public static IReader OpenReader(Stream stream, ReaderOptions? options = null)
{
stream.NotNull(nameof(stream));
return new ZipReader(stream, options ?? new ReaderOptions());
}
public static IReader Open(Stream stream, ReaderOptions? options, IEnumerable<ZipEntry> entries)
public static IReader OpenReader(
Stream stream,
ReaderOptions? options,
IEnumerable<ZipEntry> entries
)
{
stream.NotNull(nameof(stream));
return new ZipReader(stream, options ?? new ReaderOptions(), entries);

View File

@@ -28,6 +28,9 @@
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'net48' Or '$(TargetFramework)' == 'netstandard20' ">
<DefineConstants>$(DefineConstants);LEGACY_DOTNET</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'net8.0' Or '$(TargetFramework)' == 'net10.0' ">
<IsTrimmable>true</IsTrimmable>
</PropertyGroup>

View File

@@ -189,7 +189,7 @@ internal static class Utility
}
}
#if NET60_OR_GREATER
#if NET8_0_OR_GREATER
public bool ReadFully(byte[] buffer)
{
try

View File

@@ -7,52 +7,52 @@ namespace SharpCompress.Writers.GZip;
public partial class GZipWriter : IWriterOpenable<GZipWriterOptions>
{
public static IWriter Open(string filePath, GZipWriterOptions writerOptions)
public static IWriter OpenWriter(string filePath, GZipWriterOptions writerOptions)
{
filePath.NotNullOrEmpty(nameof(filePath));
return Open(new FileInfo(filePath), writerOptions);
return OpenWriter(new FileInfo(filePath), writerOptions);
}
public static IWriter Open(FileInfo fileInfo, GZipWriterOptions writerOptions)
public static IWriter OpenWriter(FileInfo fileInfo, GZipWriterOptions writerOptions)
{
fileInfo.NotNull(nameof(fileInfo));
return new GZipWriter(fileInfo.OpenWrite(), writerOptions);
}
public static IWriter Open(Stream stream, GZipWriterOptions writerOptions)
public static IWriter OpenWriter(Stream stream, GZipWriterOptions writerOptions)
{
stream.NotNull(nameof(stream));
return new GZipWriter(stream, writerOptions);
}
public static IAsyncWriter OpenAsync(
public static IAsyncWriter OpenAsyncWriter(
string path,
GZipWriterOptions writerOptions,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncWriter)Open(path, writerOptions);
return (IAsyncWriter)OpenWriter(path, writerOptions);
}
public static IAsyncWriter OpenAsync(
public static IAsyncWriter OpenAsyncWriter(
Stream stream,
GZipWriterOptions writerOptions,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncWriter)Open(stream, writerOptions);
return (IAsyncWriter)OpenWriter(stream, writerOptions);
}
public static IAsyncWriter OpenAsync(
public static IAsyncWriter OpenAsyncWriter(
FileInfo fileInfo,
GZipWriterOptions writerOptions,
CancellationToken cancellationToken = default
)
{
cancellationToken.ThrowIfCancellationRequested();
return (IAsyncWriter)Open(fileInfo, writerOptions);
return (IAsyncWriter)OpenWriter(fileInfo, writerOptions);
}
}
#endif

View File

@@ -6,9 +6,9 @@ namespace SharpCompress.Writers;
public interface IWriterFactory : IFactory
{
IWriter Open(Stream stream, WriterOptions writerOptions);
IWriter OpenWriter(Stream stream, WriterOptions writerOptions);
IAsyncWriter OpenAsync(
IAsyncWriter OpenAsyncWriter(
Stream stream,
WriterOptions writerOptions,
CancellationToken cancellationToken = default

View File

@@ -7,10 +7,10 @@ namespace SharpCompress.Writers;
public interface IWriterOpenable<TWriterOptions>
where TWriterOptions : WriterOptions
{
public static abstract IWriter Open(string filePath, TWriterOptions writerOptions);
public static abstract IWriter OpenWriter(string filePath, TWriterOptions writerOptions);
public static abstract IWriter Open(FileInfo fileInfo, TWriterOptions writerOptions);
public static abstract IWriter Open(Stream stream, TWriterOptions writerOptions);
public static abstract IWriter OpenWriter(FileInfo fileInfo, TWriterOptions writerOptions);
public static abstract IWriter OpenWriter(Stream stream, TWriterOptions writerOptions);
/// <summary>
/// Opens a Writer asynchronously.
@@ -20,19 +20,19 @@ public interface IWriterOpenable<TWriterOptions>
/// <param name="writerOptions">Writer options.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>A task that returns an IWriter.</returns>
public static abstract IAsyncWriter OpenAsync(
public static abstract IAsyncWriter OpenAsyncWriter(
Stream stream,
TWriterOptions writerOptions,
CancellationToken cancellationToken = default
);
public static abstract IAsyncWriter OpenAsync(
public static abstract IAsyncWriter OpenAsyncWriter(
string filePath,
TWriterOptions writerOptions,
CancellationToken cancellationToken = default
);
public static abstract IAsyncWriter OpenAsync(
public static abstract IAsyncWriter OpenAsyncWriter(
FileInfo fileInfo,
TWriterOptions writerOptions,
CancellationToken cancellationToken = default

Some files were not shown because too many files have changed in this diff Show More