.NET 6 解压缩大型 gzip 文本失败
.NET 6 failing at Decompress large gzip text
我必须在 .NET 6 应用程序中解压缩一些 gzip 文本,但是,对于一个 20,627 个字符长的字符串,它只能解压缩其中的大约 1/3。我正在使用的代码适用于 .NET 5 或 .NETCore 3.1 中的此字符串以及较小的压缩字符串。
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);
}
结果看起来像这样:
Star of amazing text.....
...Text is fine till 33,619 after that is allNULLNULLNULLNULL
文件的 33,618 个字符之后的其余部分只是空值。
我不知道为什么会这样。
编辑:当我发现问题不是 Blazor 而实际上是 .NET 6 时,我更新了这个。我采用了一个在 .NET Core 3.1 中工作的项目,除了针对 .NET 6 进行编译之外没有任何改变,并且得到了相同的结果错误。更新反映了这一点。
Edit2:刚刚测试并且它在 .NET 5 中工作,所以它只是在 .NET 6 中发生了这个错误。
刚刚确认 article linked in the comments below the question 包含关于该问题的有效线索。
更正后的代码为:
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);
}
这种方法改变了
gZipStream.Read(buffer, 0, buffer.Length);
至
int totalRead = 0;
while (totalRead < buffer.Length)
{
int bytesRead = gZipStream.Read(buffer, totalRead, buffer.Length - totalRead);
if (bytesRead == 0) break;
totalRead += bytesRead;
}
正确考虑了 Read
的 return 值。
如果不进行更改,该问题很容易在 任何 字符串上重复,随机性足以产生长度 > ~10kb 的 gzip。
这是压缩器,如果有人有兴趣自己测试一下
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);
}
我必须在 .NET 6 应用程序中解压缩一些 gzip 文本,但是,对于一个 20,627 个字符长的字符串,它只能解压缩其中的大约 1/3。我正在使用的代码适用于 .NET 5 或 .NETCore 3.1 中的此字符串以及较小的压缩字符串。
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);
}
结果看起来像这样:
Star of amazing text..... ...Text is fine till 33,619 after that is allNULLNULLNULLNULL
文件的 33,618 个字符之后的其余部分只是空值。
我不知道为什么会这样。
编辑:当我发现问题不是 Blazor 而实际上是 .NET 6 时,我更新了这个。我采用了一个在 .NET Core 3.1 中工作的项目,除了针对 .NET 6 进行编译之外没有任何改变,并且得到了相同的结果错误。更新反映了这一点。
Edit2:刚刚测试并且它在 .NET 5 中工作,所以它只是在 .NET 6 中发生了这个错误。
刚刚确认 article linked in the comments below the question 包含关于该问题的有效线索。
更正后的代码为:
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);
}
这种方法改变了
gZipStream.Read(buffer, 0, buffer.Length);
至
int totalRead = 0;
while (totalRead < buffer.Length)
{
int bytesRead = gZipStream.Read(buffer, totalRead, buffer.Length - totalRead);
if (bytesRead == 0) break;
totalRead += bytesRead;
}
正确考虑了 Read
的 return 值。
如果不进行更改,该问题很容易在 任何 字符串上重复,随机性足以产生长度 > ~10kb 的 gzip。
这是压缩器,如果有人有兴趣自己测试一下
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);
}