Ecng.IO
1.0.236
See the version list below for details.
dotnet add package Ecng.IO --version 1.0.236
NuGet\Install-Package Ecng.IO -Version 1.0.236
<PackageReference Include="Ecng.IO" Version="1.0.236" />
<PackageVersion Include="Ecng.IO" Version="1.0.236" />
<PackageReference Include="Ecng.IO" />
paket add Ecng.IO --version 1.0.236
#r "nuget: Ecng.IO, 1.0.236"
#:package Ecng.IO@1.0.236
#addin nuget:?package=Ecng.IO&version=1.0.236
#tool nuget:?package=Ecng.IO&version=1.0.236
Ecng.IO
A comprehensive .NET library providing compression, decompression, and file system utilities with async support.
Overview
Ecng.IO is part of the Ecng system framework by StockSharp, offering powerful helpers for:
- Data compression and decompression (GZip, Deflate, 7Zip/LZMA)
- ZIP archive extraction
- Fossil delta compression for efficient binary differencing
- File and directory operations
- Stream manipulation utilities
- Path management
Target Frameworks
- .NET Standard 2.0
- .NET 6.0
- .NET 10.0
Installation
Add a reference to the Ecng.IO project or NuGet package in your project.
<ProjectReference Include="path\to\Ecng.IO\IO.csproj" />
Features
1. Compression & Decompression
The CompressionHelper class provides extension methods for compressing and decompressing data using various algorithms.
GZip Compression
using Ecng.IO;
// Decompress GZip data to string
byte[] compressedData = GetGZipData();
string result = compressedData.UnGZip();
// Decompress GZip data to buffer
byte[] destination = new byte[1024];
int bytesWritten = compressedData.UnGZip(destination);
// Decompress from specific range
string result = compressedData.UnGZip(index: 0, count: 100);
// Modern .NET: Use spans for better performance
ReadOnlySpan<byte> compressedSpan = stackalloc byte[256];
string result = compressedSpan.UnGZip();
Deflate Compression
using Ecng.IO;
using System.IO.Compression;
// Compress data with Deflate
byte[] data = GetRawData();
byte[] compressed = data.DeflateTo();
// Decompress Deflate data
string decompressed = compressed.UnDeflate();
// Decompress to buffer
byte[] destination = new byte[1024];
int bytesWritten = compressed.UnDeflate(destination);
// Decompress with custom buffer size
byte[] decompressed = compressed.DeflateFrom(bufferSize: CompressionHelper.DefaultBufferSize);
7Zip/LZMA Compression
using Ecng.IO;
// Compress with LZMA
byte[] data = GetRawData();
byte[] compressed = data.Do7Zip();
// Decompress LZMA data
byte[] decompressed = compressed.Un7Zip();
Generic Compression API
using Ecng.IO;
using System.IO.Compression;
// Compress with any compression stream type
byte[] data = GetRawData();
byte[] compressed = data.Compress<GZipStream>(
index: 0,
count: data.Length,
level: CompressionLevel.Optimal,
bufferSize: CompressionHelper.DefaultBufferSize
);
// Decompress with any compression stream type
byte[] decompressed = compressed.Uncompress<GZipStream>(
index: 0,
count: compressed.Length,
bufferSize: CompressionHelper.DefaultBufferSize
);
Async Compression
using Ecng.IO;
using System.IO.Compression;
using System.Threading;
// Compress asynchronously
byte[] data = GetRawData();
byte[] compressed = await data.CompressAsync<GZipStream>(
level: CompressionLevel.Optimal,
bufferSize: CompressionHelper.DefaultBufferSize,
cancellationToken: CancellationToken.None
);
// Decompress asynchronously
byte[] decompressed = await compressed.UncompressAsync<DeflateStream>(
bufferSize: CompressionHelper.DefaultBufferSize,
cancellationToken: CancellationToken.None
);
// Compress stream to stream
using var inputStream = File.OpenRead("input.dat");
using var outputStream = File.Create("output.gz");
await inputStream.CompressAsync<GZipStream>(
output: outputStream,
level: CompressionLevel.Optimal,
leaveOpen: false,
bufferSize: CompressionHelper.DefaultBufferSize
);
// Decompress stream to stream
using var compressedStream = File.OpenRead("compressed.gz");
using var decompressedStream = File.Create("decompressed.dat");
await compressedStream.UncompressAsync<GZipStream>(
output: decompressedStream,
leaveOpen: false,
bufferSize: CompressionHelper.DefaultBufferSize
);
2. ZIP Archive Handling
using Ecng.IO;
// Extract all entries from ZIP
byte[] zipData = File.ReadAllBytes("archive.zip");
using (var entries = zipData.Unzip())
{
foreach (var (name, body) in entries)
{
Console.WriteLine($"File: {name}");
// Process stream...
body.CopyTo(outputStream);
}
}
// Extract with filter
using (var entries = zipData.Unzip(filter: name => name.EndsWith(".txt")))
{
foreach (var (name, body) in entries)
{
// Only .txt files are extracted
ProcessTextFile(name, body);
}
}
// Extract from stream
using var fileStream = File.OpenRead("archive.zip");
using (var entries = fileStream.Unzip(leaveOpen: false))
{
foreach (var (name, body) in entries)
{
Console.WriteLine($"Processing: {name}");
}
}
3. Fossil Delta Compression
Fossil delta compression is ideal for efficiently storing and transmitting differences between binary files, such as software updates or version control systems.
using Ecng.IO.Fossil;
using System.Threading;
// Create a delta between two versions
byte[] originalFile = File.ReadAllBytes("version1.bin");
byte[] newFile = File.ReadAllBytes("version2.bin");
byte[] delta = await Delta.Create(
origin: originalFile,
target: newFile,
token: CancellationToken.None
);
// Delta is typically much smaller than the full new file
Console.WriteLine($"Original: {originalFile.Length} bytes");
Console.WriteLine($"New: {newFile.Length} bytes");
Console.WriteLine($"Delta: {delta.Length} bytes");
// Apply delta to reconstruct the new file
byte[] reconstructed = await Delta.Apply(
origin: originalFile,
delta: delta,
token: CancellationToken.None
);
// Verify reconstruction
bool isIdentical = reconstructed.SequenceEqual(newFile); // true
// Get output size from delta without applying it
uint outputSize = Delta.OutputSize(delta);
Console.WriteLine($"Expected output size: {outputSize} bytes");
4. File and Directory Operations
The library extends the functionality available through Ecng.Common.IOHelper.
Directory Management
using Ecng.Common;
// Clear directory contents
DirectoryInfo dir = IOHelper.ClearDirectory(@"C:\temp\data");
// Clear with filter
DirectoryInfo dir = IOHelper.ClearDirectory(
@"C:\temp\data",
filter: path => Path.GetExtension(path) == ".tmp"
);
// Clear asynchronously
DirectoryInfo dir = await IOHelper.ClearDirectoryAsync(
@"C:\temp\data",
cancellationToken: cancellationToken
);
// Copy entire directory
IOHelper.CopyDirectory(@"C:\source", @"C:\destination");
// Copy asynchronously
await IOHelper.CopyDirectoryAsync(
@"C:\source",
@"C:\destination",
cancellationToken
);
// Create temporary directory
string tempDir = IOHelper.CreateTempDir();
// Returns: C:\Users\...\AppData\Local\Temp\{GUID}
// Delete directory safely (no error if not exists)
@"C:\temp\data".SafeDeleteDir();
// Delete empty directories recursively
IOHelper.DeleteEmptyDirs(@"C:\project");
// Block until directory is deleted (useful for locked files)
bool stillExists = IOHelper.BlockDeleteDir(
@"C:\temp\locked",
isRecursive: true,
iterCount: 1000,
sleep: 10
);
File Operations
using Ecng.Common;
// Copy file and make writable
string destFile = IOHelper.CopyAndMakeWritable(
@"C:\source\file.txt",
@"C:\destination"
);
// Create directory for file if needed
string filePath = @"C:\deep\nested\path\file.txt";
bool wasCreated = filePath.CreateDirIfNotExists();
// Create file with content
IOHelper.CreateFile(
rootPath: @"C:\data",
relativePath: "logs",
fileName: "app.log",
content: Encoding.UTF8.GetBytes("Log entry")
);
// Check if file is locked
bool isLocked = IOHelper.IsFileLocked(@"C:\data\file.dat");
// Get assembly/file timestamp
DateTime buildTime = IOHelper.GetTimestamp(@"C:\app\MyApp.exe");
DateTime asmTime = typeof(MyClass).Assembly.GetTimestamp();
Path Utilities
using Ecng.Common;
// Convert to full path
string fullPath = @"relative\path\file.txt".ToFullPath();
// Add relative path segment
string combined = @"C:\base".AddRelative(@"subdir\file.txt");
// Returns: C:\base\subdir\file.txt
// Expand %Documents% variable
string path = @"%Documents%\MyApp\data.db".ToFullPathIfNeed();
// Returns: C:\Users\Username\Documents\MyApp\data.db
// Get relative path
string relative = @"C:\project\src\file.cs".GetRelativePath(@"C:\project");
// Returns: src\file.cs
// Normalize paths for comparison
string normalized = @"C:\Path\To\..\File.txt".NormalizePath();
string normalized2 = @"C:\path\to\..\file.txt".NormalizePath();
// Compare paths
bool areEqual = IOHelper.IsPathsEqual(
@"C:\Path\To\File.txt",
@"c:\path\to\file.txt"
); // true
// Check if path is directory
bool isDir = @"C:\Windows".IsDirectory();
bool isDir2 = @"C:\Windows".IsPathIsDir(); // alternative
Directory Queries
using Ecng.Common;
// Get directories with pattern
IEnumerable<string> dirs = IOHelper.GetDirectories(
@"C:\projects",
searchPattern: "*.Tests",
searchOption: SearchOption.AllDirectories
);
// Get directories asynchronously
IEnumerable<string> dirs = await IOHelper.GetDirectoriesAsync(
@"C:\projects",
searchPattern: "*",
searchOption: SearchOption.TopDirectoryOnly,
cancellationToken: cancellationToken
);
// Get files asynchronously
IEnumerable<string> files = await IOHelper.GetFilesAsync(
@"C:\logs",
searchPattern: "*.log",
searchOption: SearchOption.AllDirectories,
cancellationToken: cancellationToken
);
// Check if directory exists and has content
bool hasInstall = IOHelper.CheckInstallation(@"C:\Program Files\MyApp");
// Check if directory contains files (recursive)
bool hasFiles = IOHelper.CheckDirContainFiles(@"C:\temp");
// Check if directory contains anything
bool hasContent = IOHelper.CheckDirContainsAnything(@"C:\temp");
// Get disk free space
long freeSpace = IOHelper.GetDiskFreeSpace("C:");
Console.WriteLine($"Free: {freeSpace.ToHumanReadableFileSize()}");
5. Stream Operations
Reading from Streams
using Ecng.Common;
// Read exact number of bytes
Stream stream = GetStream();
byte[] buffer = stream.ReadBuffer(size: 1024);
// Read bytes into buffer
byte[] data = new byte[512];
stream.ReadBytes(data, len: 256, pos: 0);
// Read bytes into Memory<byte>
Memory<byte> memory = new byte[512];
stream.ReadBytes(memory);
// Read full amount asynchronously (ensures all bytes are read)
byte[] buffer = new byte[1024];
int totalRead = await stream.ReadFullAsync(
buffer,
offset: 0,
bytesToRead: 1024,
cancellationToken
);
// Read typed data
int value = stream.Read<int>();
DateTime timestamp = stream.Read<DateTime>();
MyStruct data = stream.Read<MyStruct>();
// Read with dynamic size (for strings/arrays)
string text = (string)stream.Read(typeof(string));
byte[] bytes = (byte[])stream.Read(typeof(byte[]));
// Enumerate lines
foreach (string line in stream.EnumerateLines(Encoding.UTF8, leaveOpen: true))
{
Console.WriteLine(line);
}
Writing to Streams
using Ecng.Common;
Stream stream = GetStream();
// Write bytes
byte[] data = GetData();
stream.WriteBytes(data, len: data.Length, pos: 0);
// Write raw data
stream.WriteRaw(data);
stream.WriteRaw(myObject); // Converts object to bytes
// Write with length prefix
stream.WriteEx("Hello"); // Writes length + data
stream.WriteEx(new byte[] { 1, 2, 3 }); // Writes length + data
Stream Utilities
using Ecng.Common;
// Save stream to file
stream.Save(@"C:\output\data.bin");
// Save byte array to file
byte[] data = GetData();
data.Save(@"C:\output\data.bin");
// Try save with error handling
bool success = data.TrySave(
@"C:\output\data.bin",
errorHandler: ex => Console.WriteLine($"Error: {ex.Message}")
);
// Get actual buffer from MemoryStream
var ms = new MemoryStream();
ms.Write(someData, 0, someData.Length);
ArraySegment<byte> segment = ms.GetActualBuffer();
// segment contains only written data, not entire buffer
// Truncate StreamWriter
using var writer = new StreamWriter(@"C:\log.txt");
writer.WriteLine("Entry 1");
writer.Truncate(); // Clears the file
writer.WriteLine("Entry 2");
6. Process Execution
using Ecng.Common;
using System.Diagnostics;
// Execute process and capture output
int exitCode = IOHelper.Execute(
fileName: "git",
arg: "status",
output: line => Console.WriteLine($"OUT: {line}"),
error: line => Console.WriteLine($"ERR: {line}"),
waitForExit: TimeSpan.FromSeconds(30)
);
// Execute with advanced options
int exitCode = IOHelper.Execute(
fileName: "dotnet",
arg: "build",
output: line => LogOutput(line),
error: line => LogError(line),
infoHandler: info => {
info.WorkingDirectory = @"C:\project";
info.EnvironmentVariables["CUSTOM_VAR"] = "value";
},
stdInput: "input data",
priority: ProcessPriorityClass.High
);
// Execute asynchronously
int exitCode = await IOHelper.ExecuteAsync(
fileName: "npm",
arg: "install",
output: line => Console.WriteLine(line),
error: line => Console.Error.WriteLine(line),
priority: ProcessPriorityClass.BelowNormal,
cancellationToken: cancellationToken
);
7. Utility Functions
using Ecng.Common;
// Convert file size to human-readable format
long bytes = 1536000;
string size = bytes.ToHumanReadableFileSize();
// Returns: "1.5 MB"
// Get size of unmanaged type
int size = IOHelper.SizeOf<int>(); // 4
int size = IOHelper.SizeOf<DateTime>(); // 8 (stored as long)
int size = typeof(MyStruct).SizeOf();
// Open file or URL with default application
bool success = @"C:\document.pdf".OpenLink(raiseError: false);
bool success = "https://example.com".OpenLink(raiseError: true);
Buffer Sizes
The library uses a default buffer size for compression operations:
// Default buffer size: 80 KB
const int bufferSize = CompressionHelper.DefaultBufferSize; // 81920 bytes
You can customize buffer sizes for performance tuning:
// Use smaller buffer for memory-constrained environments
byte[] compressed = data.Compress<GZipStream>(bufferSize: 4096);
// Use larger buffer for better throughput
byte[] compressed = data.Compress<GZipStream>(bufferSize: 1024 * 1024);
Error Handling
All methods throw standard .NET exceptions:
ArgumentNullException- When required parameters are nullArgumentOutOfRangeException- When sizes or indices are invalidIOException- When I/O operations failUnauthorizedAccessException- When access is deniedDirectoryNotFoundException/FileNotFoundException- When paths don't exist
try
{
var data = compressedData.UnGZip();
}
catch (ArgumentNullException ex)
{
// Input was null
}
catch (IOException ex)
{
// Decompression failed
}
Thread Safety
CompressionHelpermethods are thread-safe as they operate on method parameters- Stream operations are not inherently thread-safe - synchronize access if needed
- File operations should be synchronized when accessing the same files from multiple threads
- Async methods support
CancellationTokenfor cooperative cancellation
Performance Tips
- Use async methods for I/O-bound operations to avoid blocking threads
- Use Span/Memory APIs on .NET 6.0+ for better performance and less allocation
- Choose appropriate compression levels:
CompressionLevel.Fastest- Quick but larger filesCompressionLevel.Optimal- Balanced (default)CompressionLevel.SmallestSize- Slow but smallest files (.NET 7+)
- Adjust buffer sizes based on your data and memory constraints
- Use Fossil Delta for incremental updates instead of full file transfers
Examples
Example 1: Compress and Save File
using Ecng.IO;
using System.IO.Compression;
// Read, compress, and save
byte[] original = File.ReadAllBytes(@"C:\data\large-file.json");
byte[] compressed = original.Compress<GZipStream>(
level: CompressionLevel.Optimal
);
compressed.Save(@"C:\data\large-file.json.gz");
Console.WriteLine($"Original: {original.Length.ToHumanReadableFileSize()}");
Console.WriteLine($"Compressed: {compressed.Length.ToHumanReadableFileSize()}");
Console.WriteLine($"Ratio: {(100.0 * compressed.Length / original.Length):F1}%");
Example 2: Process ZIP Archive
using Ecng.IO;
byte[] zipData = File.ReadAllBytes(@"C:\downloads\archive.zip");
using (var entries = zipData.Unzip(filter: name => name.EndsWith(".csv")))
{
foreach (var (fileName, stream) in entries)
{
Console.WriteLine($"Processing: {fileName}");
using var reader = new StreamReader(stream);
string csvContent = reader.ReadToEnd();
// Process CSV...
ProcessCsvData(csvContent);
}
}
Example 3: Incremental Binary Updates with Fossil Delta
using Ecng.IO.Fossil;
// Server side: Create delta
byte[] v1 = File.ReadAllBytes(@"app-v1.0.exe");
byte[] v2 = File.ReadAllBytes(@"app-v2.0.exe");
byte[] delta = await Delta.Create(v1, v2, CancellationToken.None);
// Upload only the delta (much smaller than full v2)
await UploadToServer("update-1.0-to-2.0.delta", delta);
// Client side: Apply delta
byte[] currentVersion = File.ReadAllBytes(@"app.exe");
byte[] deltaUpdate = await DownloadFromServer("update-1.0-to-2.0.delta");
byte[] newVersion = await Delta.Apply(currentVersion, deltaUpdate, CancellationToken.None);
File.WriteAllBytes(@"app.exe", newVersion);
Example 4: Async Directory Processing
using Ecng.Common;
// Find all log files and compress them
var logFiles = await IOHelper.GetFilesAsync(
@"C:\logs",
searchPattern: "*.log",
searchOption: SearchOption.AllDirectories,
cancellationToken: cancellationToken
);
foreach (string logFile in logFiles)
{
byte[] content = await File.ReadAllBytesAsync(logFile, cancellationToken);
byte[] compressed = await content.CompressAsync<GZipStream>(
cancellationToken: cancellationToken
);
await File.WriteAllBytesAsync(
logFile + ".gz",
compressed,
cancellationToken
);
Console.WriteLine($"Compressed: {logFile}");
}
Example 5: Stream Processing Pipeline
using Ecng.IO;
using Ecng.Common;
using System.IO.Compression;
// Create a processing pipeline
await using var inputFile = File.OpenRead(@"C:\data\input.txt");
await using var compressed = new MemoryStream();
await using var encrypted = new MemoryStream();
// Compress
await inputFile.CompressAsync<GZipStream>(
output: compressed,
level: CompressionLevel.Optimal,
leaveOpen: true
);
compressed.Position = 0;
// Further processing...
// (e.g., encrypt, hash, etc.)
// Save final result
compressed.Position = 0;
await using var output = File.Create(@"C:\data\output.bin");
await compressed.CopyToAsync(output);
License
Copyright © StockSharp 2010-2025
Related Libraries
- Ecng.Common - Core utilities and extensions
- Ecng.Lzma - LZMA compression implementation
- Ecng.Serialization - Serialization utilities
Support
For issues and questions, please visit the StockSharp repository or documentation.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Ecng.Common (>= 1.0.231)
- Ecng.Lzma (>= 1.0.65)
-
net10.0
- Ecng.Common (>= 1.0.231)
- Ecng.Lzma (>= 1.0.65)
-
net6.0
- Ecng.Common (>= 1.0.231)
- Ecng.Lzma (>= 1.0.65)
NuGet packages (11)
Showing the top 5 NuGet packages that depend on Ecng.IO:
| Package | Downloads |
|---|---|
|
StockSharp.Algo
Trading algorithms. More info on web site https://stocksharp.com/store/ |
|
|
StockSharp.Fix
FIX/FAST |
|
|
StockSharp.DukasCopy
DukasCopy |
|
|
StockSharp.Web.Api.Interfaces
StockSharp WebApi |
|
|
StockSharp.Quandl
Trading and algorithmic trading platform (stock markets, forex, bitcoins and options). .NET API for InteractiveBrokers, GainCapital, OANDA, FIX/FAST, Binance etc. More info on web site https://stocksharp.com/store/api/ |
GitHub repositories (1)
Showing the top 1 popular GitHub repositories that depend on Ecng.IO:
| Repository | Stars |
|---|---|
|
StockSharp/StockSharp
Algorithmic trading and quantitative trading open source platform to develop trading robots (stock markets, forex, crypto, bitcoins, and options).
|
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.238 | 0 | 12/25/2025 |
| 1.0.237 | 0 | 12/25/2025 |
| 1.0.236 | 58 | 12/22/2025 |
| 1.0.235 | 64 | 12/21/2025 |
| 1.0.234 | 213 | 12/19/2025 |
| 1.0.233 | 198 | 12/19/2025 |
| 1.0.232 | 317 | 12/17/2025 |
| 1.0.231 | 309 | 12/15/2025 |
| 1.0.230 | 168 | 12/12/2025 |
| 1.0.229 | 121 | 12/12/2025 |
| 1.0.228 | 253 | 11/29/2025 |
| 1.0.227 | 124 | 11/28/2025 |
| 1.0.226 | 129 | 11/28/2025 |
| 1.0.225 | 185 | 11/27/2025 |
| 1.0.224 | 283 | 11/24/2025 |
| 1.0.223 | 193 | 11/24/2025 |
| 1.0.222 | 194 | 11/23/2025 |
| 1.0.221 | 244 | 11/22/2025 |
| 1.0.220 | 1,008 | 11/20/2025 |
| 1.0.219 | 435 | 11/18/2025 |
| 1.0.218 | 401 | 11/18/2025 |
| 1.0.217 | 386 | 11/13/2025 |
| 1.0.216 | 288 | 11/10/2025 |
| 1.0.215 | 1,153 | 11/1/2025 |
| 1.0.214 | 244 | 10/28/2025 |
| 1.0.213 | 247 | 10/27/2025 |
| 1.0.212 | 192 | 10/27/2025 |
| 1.0.211 | 125 | 10/25/2025 |
| 1.0.210 | 1,198 | 10/3/2025 |
| 1.0.209 | 413 | 9/25/2025 |
| 1.0.208 | 4,897 | 8/30/2025 |
| 1.0.207 | 3,051 | 7/13/2025 |
| 1.0.206 | 212 | 7/13/2025 |
| 1.0.205 | 190 | 7/12/2025 |
| 1.0.204 | 606 | 7/8/2025 |
| 1.0.203 | 3,375 | 6/16/2025 |
| 1.0.202 | 384 | 6/9/2025 |
| 1.0.201 | 281 | 6/8/2025 |
| 1.0.200 | 768 | 5/21/2025 |
| 1.0.199 | 216 | 5/17/2025 |
| 1.0.198 | 820 | 5/12/2025 |
| 1.0.197 | 277 | 5/12/2025 |
| 1.0.196 | 377 | 4/17/2025 |
| 1.0.195 | 2,836 | 3/20/2025 |
| 1.0.194 | 254 | 3/19/2025 |
| 1.0.193 | 1,407 | 2/26/2025 |
| 1.0.192 | 186 | 2/26/2025 |
| 1.0.191 | 2,595 | 2/5/2025 |
| 1.0.190 | 568 | 1/21/2025 |
| 1.0.189 | 667 | 1/14/2025 |
| 1.0.188 | 220 | 1/12/2025 |
| 1.0.187 | 210 | 1/10/2025 |
| 1.0.186 | 3,107 | 11/18/2024 |
| 1.0.185 | 652 | 11/7/2024 |
| 1.0.184 | 358 | 10/19/2024 |
| 1.0.183 | 2,272 | 10/5/2024 |
| 1.0.182 | 2,228 | 9/18/2024 |
| 1.0.181 | 222 | 9/17/2024 |
| 1.0.180 | 1,200 | 9/1/2024 |
| 1.0.179 | 6,646 | 6/12/2024 |
| 1.0.178 | 1,203 | 5/28/2024 |
| 1.0.177 | 1,651 | 5/4/2024 |
| 1.0.176 | 2,413 | 4/14/2024 |
| 1.0.175 | 1,978 | 3/28/2024 |
| 1.0.174 | 269 | 3/17/2024 |
| 1.0.173 | 2,052 | 2/23/2024 |
| 1.0.172 | 221 | 2/23/2024 |
| 1.0.171 | 1,496 | 2/18/2024 |
| 1.0.170 | 232 | 2/16/2024 |
| 1.0.169 | 942 | 2/13/2024 |
| 1.0.168 | 862 | 2/8/2024 |
| 1.0.167 | 1,140 | 2/4/2024 |
| 1.0.166 | 1,111 | 1/23/2024 |
| 1.0.165 | 2,000 | 1/12/2024 |
| 1.0.164 | 2,250 | 1/2/2024 |
| 1.0.163 | 402 | 12/29/2023 |
| 1.0.162 | 5,460 | 11/12/2023 |
| 1.0.161 | 181 | 11/10/2023 |
| 1.0.160 | 162 | 11/10/2023 |
| 1.0.159 | 401 | 11/9/2023 |
| 1.0.158 | 544 | 11/3/2023 |
| 1.0.157 | 207 | 11/1/2023 |
| 1.0.156 | 189 | 11/1/2023 |
| 1.0.155 | 5,755 | 9/8/2023 |
| 1.0.154 | 442 | 9/8/2023 |
| 1.0.153 | 415 | 9/3/2023 |
| 1.0.152 | 319 | 8/21/2023 |
| 1.0.151 | 722 | 8/14/2023 |
| 1.0.150 | 847 | 8/10/2023 |
| 1.0.149 | 5,409 | 6/29/2023 |
| 1.0.148 | 4,304 | 5/27/2023 |
| 1.0.147 | 1,023 | 5/19/2023 |
| 1.0.146 | 4,643 | 5/8/2023 |
| 1.0.145 | 3,575 | 4/21/2023 |
| 1.0.144 | 6,313 | 4/3/2023 |
| 1.0.143 | 4,062 | 3/13/2023 |
| 1.0.142 | 2,589 | 3/6/2023 |
| 1.0.141 | 1,368 | 2/26/2023 |
| 1.0.140 | 7,923 | 2/9/2023 |
| 1.0.139 | 4,136 | 2/7/2023 |
| 1.0.138 | 432 | 2/4/2023 |
| 1.0.137 | 3,246 | 2/2/2023 |
| 1.0.136 | 3,170 | 1/30/2023 |
| 1.0.135 | 4,357 | 1/18/2023 |
| 1.0.134 | 9,641 | 12/30/2022 |
| 1.0.133 | 1,588 | 12/23/2022 |
| 1.0.132 | 3,873 | 12/12/2022 |
| 1.0.131 | 6,805 | 12/4/2022 |
| 1.0.130 | 490 | 12/4/2022 |
| 1.0.129 | 518 | 11/30/2022 |
| 1.0.128 | 478 | 11/28/2022 |
| 1.0.127 | 2,594 | 11/18/2022 |
| 1.0.126 | 5,969 | 11/11/2022 |
| 1.0.125 | 526 | 11/11/2022 |
| 1.0.124 | 516 | 11/10/2022 |
| 1.0.123 | 565 | 11/5/2022 |
| 1.0.122 | 1,942 | 11/4/2022 |
| 1.0.121 | 18,511 | 11/1/2022 |
| 1.0.120 | 20,903 | 10/16/2022 |
| 1.0.119 | 681 | 9/25/2022 |
| 1.0.118 | 5,057 | 9/10/2022 |
| 1.0.117 | 42,247 | 9/8/2022 |
| 1.0.116 | 605 | 9/8/2022 |
| 1.0.115 | 616 | 9/8/2022 |
| 1.0.114 | 606 | 9/4/2022 |
| 1.0.113 | 83,379 | 8/24/2022 |
| 1.0.112 | 4,853 | 8/8/2022 |
| 1.0.111 | 2,511 | 7/26/2022 |
| 1.0.110 | 630 | 7/26/2022 |
| 1.0.109 | 43,261 | 7/19/2022 |
| 1.0.108 | 42,358 | 7/18/2022 |
| 1.0.107 | 3,885 | 7/13/2022 |
| 1.0.106 | 643 | 7/11/2022 |
| 1.0.105 | 633 | 7/8/2022 |
| 1.0.104 | 1,658 | 6/30/2022 |
| 1.0.103 | 1,646 | 6/18/2022 |
| 1.0.102 | 690 | 6/6/2022 |
| 1.0.101 | 84,548 | 4/30/2022 |
| 1.0.100 | 670 | 4/20/2022 |
| 1.0.99 | 676 | 4/10/2022 |
| 1.0.98 | 658 | 4/7/2022 |
| 1.0.97 | 654 | 4/7/2022 |
| 1.0.96 | 659 | 4/2/2022 |
| 1.0.95 | 7,391 | 3/29/2022 |
| 1.0.94 | 626 | 3/27/2022 |
| 1.0.93 | 238,112 | 1/24/2022 |
| 1.0.92 | 147,801 | 12/29/2021 |
| 1.0.91 | 25,860 | 12/20/2021 |
| 1.0.90 | 594 | 12/13/2021 |
| 1.0.89 | 50,640 | 12/6/2021 |
| 1.0.88 | 527 | 12/2/2021 |
| 1.0.87 | 27,599 | 11/29/2021 |
| 1.0.86 | 25,756 | 11/22/2021 |
| 1.0.85 | 609 | 11/17/2021 |
| 1.0.84 | 26,660 | 11/13/2021 |
| 1.0.83 | 564 | 11/10/2021 |
| 1.0.82 | 530 | 11/9/2021 |
| 1.0.81 | 56,305 | 11/5/2021 |
| 1.0.80 | 605 | 11/5/2021 |
| 1.0.79 | 568 | 11/4/2021 |
| 1.0.78 | 566 | 11/4/2021 |
| 1.0.77 | 582 | 11/3/2021 |
| 1.0.76 | 638 | 10/30/2021 |
| 1.0.75 | 29,421 | 10/21/2021 |
| 1.0.74 | 676 | 10/17/2021 |
| 1.0.73 | 55,263 | 10/14/2021 |
| 1.0.72 | 4,620 | 10/13/2021 |
| 1.0.71 | 547 | 10/12/2021 |
| 1.0.70 | 29,110 | 10/11/2021 |
| 1.0.69 | 574 | 10/9/2021 |
| 1.0.68 | 32,359 | 10/7/2021 |
| 1.0.67 | 30,969 | 10/7/2021 |
| 1.0.66 | 528 | 10/7/2021 |
| 1.0.65 | 605 | 10/6/2021 |
| 1.0.64 | 636 | 9/28/2021 |
| 1.0.63 | 30,311 | 9/23/2021 |
| 1.0.62 | 667 | 9/10/2021 |
| 1.0.61 | 603 | 9/9/2021 |
| 1.0.60 | 569 | 9/8/2021 |
| 1.0.59 | 563 | 9/8/2021 |
| 1.0.58 | 28,709 | 9/6/2021 |
| 1.0.57 | 595 | 8/31/2021 |
| 1.0.56 | 555 | 8/30/2021 |
| 1.0.55 | 29,737 | 7/31/2021 |
| 1.0.54 | 54,900 | 7/30/2021 |
| 1.0.53 | 646 | 7/26/2021 |
| 1.0.52 | 81,898 | 7/5/2021 |
| 1.0.51 | 601 | 7/1/2021 |
| 1.0.50 | 57,456 | 6/4/2021 |
| 1.0.49 | 82,966 | 4/26/2021 |
| 1.0.48 | 28,921 | 4/19/2021 |
| 1.0.47 | 135,614 | 4/7/2021 |
| 1.0.46 | 27,904 | 4/3/2021 |
| 1.0.45 | 163,167 | 3/22/2021 |
| 1.0.44 | 101,747 | 3/4/2021 |
| 1.0.43 | 28,001 | 2/26/2021 |
| 1.0.42 | 151,303 | 2/2/2021 |
| 1.0.41 | 101,381 | 1/24/2021 |
| 1.0.40 | 663 | 1/23/2021 |
| 1.0.39 | 51,469 | 1/20/2021 |
| 1.0.38 | 649 | 1/20/2021 |
| 1.0.37 | 26,263 | 1/18/2021 |
| 1.0.36 | 25,378 | 1/16/2021 |
| 1.0.35 | 104,397 | 12/16/2020 |
| 1.0.34 | 52,863 | 12/14/2020 |
| 1.0.33 | 29,849 | 12/9/2020 |
| 1.0.32 | 789 | 12/6/2020 |
| 1.0.31 | 718 | 12/2/2020 |
| 1.0.30 | 26,331 | 12/1/2020 |
| 1.0.29 | 145,486 | 11/12/2020 |
| 1.0.29-atestpub | 544 | 11/11/2020 |
| 1.0.28 | 26,970 | 10/11/2020 |
| 1.0.27 | 100,051 | 9/9/2020 |
| 1.0.26 | 25,460 | 9/3/2020 |
| 1.0.25 | 26,157 | 8/20/2020 |
| 1.0.24 | 75,642 | 8/9/2020 |
| 1.0.23 | 25,616 | 7/28/2020 |
| 1.0.22 | 25,427 | 7/19/2020 |
| 1.0.21 | 49,317 | 7/6/2020 |
| 1.0.20 | 75,996 | 6/6/2020 |
| 1.0.19 | 26,421 | 6/4/2020 |
| 1.0.18 | 51,032 | 5/29/2020 |
| 1.0.17 | 51,073 | 5/21/2020 |
| 1.0.16 | 848 | 5/17/2020 |
| 1.0.15 | 51,749 | 5/12/2020 |
| 1.0.14 | 102,483 | 5/4/2020 |
| 1.0.13 | 865 | 4/24/2020 |
| 1.0.12 | 4,001 | 4/22/2020 |
| 1.0.11 | 746 | 4/22/2020 |
| 1.0.10 | 738 | 4/21/2020 |
| 1.0.9 | 28,106 | 4/18/2020 |
| 1.0.8 | 26,168 | 4/16/2020 |
| 1.0.7 | 737 | 4/16/2020 |
| 1.0.6 | 22,188 | 4/15/2020 |
| 1.0.5 | 23,592 | 4/11/2020 |
| 1.0.4 | 23,420 | 4/3/2020 |
| 1.0.3 | 772 | 4/1/2020 |
| 1.0.2 | 10,107 | 3/27/2020 |
| 1.0.1 | 9,105 | 3/22/2020 |
| 1.0.0 | 2,612 | 3/22/2020 |