public static async Task DecompressL33TZipAsync( Stream inputStream, Stream outputStream, IProgress <double> progress = null, CancellationToken ct = default) { //Get extracted content length long fileLength; using (var reader = new AsyncBinaryReader(inputStream, new UTF8Encoding(), true)) { var fileHeader = new string(await reader.ReadCharsAsync(4, ct)); switch (fileHeader.ToLower()) { case L33THeader: fileLength = await reader.ReadInt32Async(ct); break; case L66THeader: fileLength = await reader.ReadInt64Async(ct); break; default: throw new InvalidOperationException($"Header '{fileHeader}' is not recognized as a valid type"); } //Skip deflate specification (2 Byte) reader.BaseStream.Position += 2; } //Extract content var buffer = new byte[BufferSize]; int bytesRead; var totalBytesRead = 0L; var lastProgress = 0d; using var compressedStream = new DeflateStream(inputStream, CompressionMode.Decompress); while ((bytesRead = await compressedStream.ReadAsync(buffer, 0, buffer.Length, ct)) > 0) { ct.ThrowIfCancellationRequested(); if (bytesRead > fileLength) { totalBytesRead += fileLength; await outputStream.WriteAsync(buffer, 0, (int)fileLength, ct); } else if (totalBytesRead + bytesRead <= fileLength) { totalBytesRead += bytesRead; await outputStream.WriteAsync(buffer, 0, bytesRead, ct); } else if (totalBytesRead + bytesRead > fileLength) { var leftToRead = fileLength - totalBytesRead; totalBytesRead += leftToRead; await outputStream.WriteAsync(buffer, 0, (int)leftToRead, ct); } var newProgress = (double)totalBytesRead / fileLength * 100; if (newProgress - lastProgress > 1) { progress?.Report(newProgress); lastProgress = newProgress; } if (totalBytesRead >= fileLength) { break; } } }
public async Task TestAsyncBinaryReader() { byte customByte = 39; bool customBool = Unsafe.As <byte, bool>(ref customByte); object[] expectedResults = { true, false, customBool, (byte)42, (sbyte)-28, (short)-279, (ushort)64221, (int)-288888, (uint)3310229011, (float)3811.55f, (long)-19195205991011, (ulong)11223372036854775807, (double)Math.PI, (decimal)295222.2811m }; using (var ms = new MemoryStream()) { using (var wr = new BinaryWriter(ms, Encoding.Default, leaveOpen: true)) { foreach (dynamic obj in expectedResults) { wr.Write(obj); } } ms.Position = 0; using (var rd = new AsyncBinaryReader(ms, Encoding.Default, leaveOpen: true)) { foreach (var obj in expectedResults) { switch (obj) { case bool b8: ////Assert.Equal(b8, await rd.ReadBooleanAsync()); if (b8) { Assert.True(await rd.ReadBooleanAsync()); } else { Assert.False(await rd.ReadBooleanAsync()); } break; case byte u8: Assert.Equal(u8, await rd.ReadByteAsync()); break; case sbyte s8: Assert.Equal(s8, await rd.ReadSByteAsync()); break; case short s16: Assert.Equal(s16, await rd.ReadInt16Async()); break; case ushort u16: Assert.Equal(u16, await rd.ReadUInt16Async()); break; case int s32: Assert.Equal(s32, await rd.ReadInt32Async()); break; case uint u32: Assert.Equal(u32, await rd.ReadUInt32Async()); break; case long s64: Assert.Equal(s64, await rd.ReadInt64Async()); break; case ulong u64: Assert.Equal(u64, await rd.ReadUInt64Async()); break; case float f32: Assert.Equal(f32, await rd.ReadSingleAsync()); break; case double f64: Assert.Equal(f64, await rd.ReadDoubleAsync()); break; case decimal d128: Assert.Equal(d128, await rd.ReadDecimalAsync()); break; } } } } }