这是真实项目中的代码,用于该问题,因此一些数据是硬编码的:
static void Main(string[] args)
{
Console.WriteLine("Starting. " + Environment.Version);
using (var stream = new FileStream(@"stream_test.txt", FileMode.Open))
{
stream.Position = 0;
// .NET implements Deflate (RFC 1951) but not zlib (RFC 1950),
// so we have to skip the first two bytes.
stream.ReadByte();
stream.ReadByte();
var zipStream = new DeflateStream(stream, CompressionMode.Decompress, true);
// Hardcoded length from real project. In the previous .Net versions this is size of final result
long bytesToRead = (long)262 * 350;
var buffer = new byte[bytesToRead];
int bytesWereRead = zipStream.Read(buffer, 0, (int)bytesToRead);
if (bytesWereRead != bytesToRead)
{
throw new Exception("ZIP stream was not fully decompressed.");
}
Console.WriteLine("Ok");
Console.ReadKey();
}
}
解压缩的问题并不出现在每个流上,因此可以在GitHub上找到带有项目代码的输入文件。https://github.com/dimsa/Net6DeflateStreamIssue/tree/main/DeflateStreamTest
此代码在上运行良好
- .NET Framework(在2.0、3.5、4上进行了测试(
- .NET标准2.1和
- .NET 5
.NET 6失败。Net 6中解压缩的数据的长度不正确。
是否有任何解决方法,或者应该使用其他压缩库?
DeflateStream在.NET6中的操作方式发生了重大变化。您可以在本Microsoft文档中阅读有关它和建议操作的详细信息。
基本上,您需要包装.Read
操作,并检查读取的长度与预期的长度,因为该操作现在可能在读取完整长度之前返回。您的代码可能如下所示(基于文档中的示例(:
int totalRead = 0;
var buffer = new byte[bytesToRead];
while (totalRead < buffer.Length)
{
int bytesRead = zipStream.Read(buffer.Slice(totalRead));
if (bytesRead == 0) break;
totalRead += bytesRead;
}
这是另一个解决方案。只是一种不同的方式。
var totalRead = 0;
var byteRead = 0;
var buffer = new byte[dataLength];
while (totalRead < buffer.Length)
{
byteRead = gZipStream.Read(buffer, totalRead, buffer.Length - totalRead);
if (byteRead == 0) break;
totalRead += byteRead;
}