Tengo que descomprimir un texto gzip en la aplicación .NET 6, sin embargo, en una cadena que tiene 20,627 caracteres, solo se descomprime alrededor de 1/3. El código que estoy usando funciona para esta cadena en .NET 5 o .NETCore 3.1, así como para cadenas comprimidas más pequeñas.
public static string Decompress(this string compressedText) { var gZipBuffer = Convert.FromBase64String(compressedText); using var memoryStream = new MemoryStream(); int dataLength = BitConverter.ToInt32(gZipBuffer, 0); memoryStream.Write(gZipBuffer, 4, gZipBuffer.Length - 4); var buffer = new byte[dataLength]; memoryStream.Position = 0; using (var gZipStream = new GZipStream(memoryStream, CompressionMode.Decompress)) { gZipStream.Read(buffer, 0, buffer.Length); } return Encoding.UTF8.GetString(buffer); }Los resultados se parecen a esto:
Estrella de texto asombroso... ...El texto está bien hasta 33,619 después de eso es NULLNULLNULLNULL
El resto del archivo después de los 33.618 caracteres es simplemente nulo.
No tengo idea de por qué sucede esto.
Editar: actualicé esto cuando descubrí que el problema no era Blazor, sino .NET 6. Tomé un proyecto que funcionaba en .NET Core 3.1, no cambió nada más que compilar para .NET 6 y obtuve el mismo error. La actualización refleja esto.
Edit2: Acabo de probar y funciona en .NET 5, por lo que solo ocurre en .NET 6 este error.
Acabo de confirmar que el artículo vinculado en los comentarios debajo de la pregunta contiene una pista válida sobre el problema.
El código corregido sería:
string Decompress(string compressedText) { var gZipBuffer = Convert.FromBase64String(compressedText); using var memoryStream = new MemoryStream(); int dataLength = BitConverter.ToInt32(gZipBuffer, 0); memoryStream.Write(gZipBuffer, 4, gZipBuffer.Length - 4); var buffer = new byte[dataLength]; memoryStream.Position = 0; using var gZipStream = new GZipStream(memoryStream, CompressionMode.Decompress); int totalRead = 0; while (totalRead < buffer.Length) { int bytesRead = gZipStream.Read(buffer, totalRead, buffer.Length - totalRead); if (bytesRead == 0) break; totalRead += bytesRead; } return Encoding.UTF8.GetString(buffer); }Este enfoque cambia
gZipStream.Read(buffer, 0, buffer.Length);para
int totalRead = 0; while (totalRead < buffer.Length) { int bytesRead = gZipStream.Read(buffer, totalRead, buffer.Length - totalRead); if (bytesRead == 0) break; totalRead += bytesRead; } que tiene en cuenta el valor de retorno de Read correctamente.
Sin el cambio, el problema se puede repetir fácilmente en cualquier cadena lo suficientemente aleatoria como para producir un gzip de longitud > ~10kb.
Aquí está el compresor, si alguien está interesado en probarlo por su cuenta.
string Compress(string plainText) { var buffer = Encoding.UTF8.GetBytes(plainText); using var memoryStream = new MemoryStream(); var lengthBytes = BitConverter.GetBytes((int)buffer.Length); memoryStream.Write(lengthBytes, 0, lengthBytes.Length); using var gZipStream = new GZipStream(memoryStream, CompressionMode.Compress); gZipStream.Write(buffer, 0, buffer.Length); gZipStream.Flush(); var gZipBuffer = memoryStream.ToArray(); return Convert.ToBase64String(gZipBuffer); }