C#GZipStream压缩数据,但解压缩返回空流



我有以下代码:

public static async Task<string> Compress(string inputString)
{
var bytes = Encoding.Unicode.GetBytes(inputString);
await using var input = new MemoryStream(bytes);
await using var output = new MemoryStream();
await using var stream = new GZipStream(output, CompressionLevel.SmallestSize);
await input.CopyToAsync(stream);
return Convert.ToBase64String(output.ToArray());
}
public static async Task<string> Decompress(string inputString)
{
var bytes = Convert.FromBase64String(inputString);
await using var output = new MemoryStream();
await using var input = new MemoryStream(bytes);
await using var stream = new GZipStream(input, CompressionMode.Decompress);
await stream.CopyToAsync(output);
await stream.FlushAsync();

return Encoding.Unicode.GetString(output.ToArray());
}

当我尝试压缩字符串"Hello World"时,压缩的Base64编码字符串为"H4sIAAAAAAACCg==">

当我尝试解压缩Base64编码的字符串"H4sIAAAAAAACCg=="时,方法decompress返回一个空字符串。

您没有得到正确的压缩字符串。output.ToArray()streamGZipStream被刷新之前被调用,因此outputMemoryStream的内容还不是完整的压缩字节。您需要在await input.CopyToAsync(stream);之后添加await stream.FlushAsync();

GZipStream及其内部DeflateStream被设计为在调用Dispose时隐式刷新其内部缓冲区(请参阅https://github.com/dotnet/runtime/blob/main/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/DeflateStream.cs)。

对于使用C#8.0中引入的不带大括号的语句,其范围受到包含范围的限制。在这种情况下,包含的作用域是方法本身,这意味着当方法最终退出时,对象超出了作用域。因此,从streamoutput的隐式刷新发生在Convert.ToBase64String(output.ToArray())之后。

为了避免这种情况,我们可以添加大括号来限制作用域(请参阅下面的示例(,或者显式刷新stream(这不是对所有.NET版本都有效,请参阅https://github.com/dotnet/runtime/commit/728aa671567d498c1acb6e13cb5cf4f7a883acf7。

public static async Task<string> Compress(string inputString)
{
var bytes = Encoding.Unicode.GetBytes(inputString);

await using (var input = new MemoryStream(bytes))
{
await using (var output = new MemoryStream())
{
await using (var stream = new GZipStream(output, CompressionLevel.SmallestSize))
{
await input.CopyToAsync(stream);
}

return Convert.ToBase64String(output.ToArray());
}
}
}
public static async Task<string> Decompress(string inputString)
{
var bytes = Convert.FromBase64String(inputString);
await using (var output = new MemoryStream())
{
await using (var input = new MemoryStream(bytes))
{
await using (var stream = new GZipStream(input, CompressionMode.Decompress))
{
await stream.CopyToAsync(output);
}
}
return Encoding.Unicode.GetString(output.ToArray());
}
}

相关内容

  • 没有找到相关文章

最新更新