gpt4 book ai didi

c# - GZipStream 和 DeflateStream 不会解压所有字节

转载 作者:IT王子 更新时间:2023-10-29 04:03:39 24 4
gpt4 key购买 nike

我需要一种在 .net 中压缩图像的方法,所以我研究了使用 .net GZipStream 类(或 DeflateStream)。但是我发现解压缩并不总是成功,有时图像可以很好地解压缩,有时我会收到 GDI+ 错误,表示某些内容已损坏。

在调查这个问题后,我发现解压缩并没有返回它压缩的所有字节。因此,如果我压缩了 2257974 字节,我有时只能得到 2257870 字节(实数)。

最有趣的是有时它会起作用。所以我创建了这个只压缩 10 个字节的小测试方法,现在我什么也得不到。

我尝试使用 GZipStream 和 DeflateStream 这两个压缩类,并仔细检查了我的代码是否存在可能的错误。我什至尝试将流定位到 0 并刷新所有流,但没有成功。

这是我的代码:

    public static void TestCompression()
{
byte[] test = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

byte[] result = Decompress(Compress(test));

// This will fail, result.Length is 0
Debug.Assert(result.Length == test.Length);
}

public static byte[] Compress(byte[] data)
{
var compressedStream = new MemoryStream();
var zipStream = new GZipStream(compressedStream, CompressionMode.Compress);
zipStream.Write(data, 0, data.Length);
return compressedStream.ToArray();
}

public static byte[] Decompress(byte[] data)
{
var compressedStream = new MemoryStream(data);
var zipStream = new GZipStream(compressedStream, CompressionMode.Decompress);
var resultStream = new MemoryStream();

var buffer = new byte[4096];
int read;

while ((read = zipStream.Read(buffer, 0, buffer.Length)) > 0) {
resultStream.Write(buffer, 0, read);
}

return resultStream.ToArray();
}

最佳答案

在添加所有要压缩的数据后,您需要Close() ZipStream;它在内部保留了一个未写入字节的缓冲区(即使您 Flush())需要写入。

更一般地说,StreamIDisposable,因此您还应该使用 每个...(是的,我知道 MemoryStream 不会丢失任何数据,但如果你不养成这个习惯,它会与其他 Stream 一起咬你)。

public static byte[] Compress(byte[] data)
{
using (var compressedStream = new MemoryStream())
using (var zipStream = new GZipStream(compressedStream, CompressionMode.Compress))
{
zipStream.Write(data, 0, data.Length);
zipStream.Close();
return compressedStream.ToArray();
}
}

public static byte[] Decompress(byte[] data)
{
using(var compressedStream = new MemoryStream(data))
using(var zipStream = new GZipStream(compressedStream, CompressionMode.Decompress))
using (var resultStream = new MemoryStream())
{ ... }
}

[编辑:更新评论]不要使用诸如MemoryStream之类的东西——这总是一个有趣的东西,栅栏两边都有很多选票:但最终......

(修辞 - 我们都知道答案...) MemoryStream 是如何实现的?它是 byte[](由 .NET 拥有)吗?它是内存映射文件(由操作系统拥有)吗?

您没有使用的原因是您让内部实现细节的知识改变了您针对公共(public) API 进行编码的方式 - 即您刚刚违反了封装法则。公共(public) API 说:我是 IDisposable;你欠我的;因此,你的工作是在你完成后 Dispose() 我。

关于c# - GZipStream 和 DeflateStream 不会解压所有字节,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/271260/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com