public static async Task <bool> IsL33TZipAsync(Stream stream, CancellationToken ct = default) { var oldPosition = stream.Position; try { using var reader = new AsyncBinaryReader(stream, new UTF8Encoding(), true); var fileHeader = new string(await reader.ReadCharsAsync(4, ct)); switch (fileHeader.ToLower()) { case L33THeader: case L66THeader: break; default: throw new InvalidOperationException($"Header '{fileHeader}' is not recognized as a valid type"); } return(true); } #pragma warning disable CA1031 // Do not catch general exception types catch (Exception) { return(false); } #pragma warning restore CA1031 // Do not catch general exception types finally { stream.Position = oldPosition; } }
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; } } }