GZipStream And DeflateStream will not decompress all bytes(GZipStream 和 DeflateStream 不会解压缩所有字节)
问题描述
我需要一种在 .net 中压缩图像的方法,所以我研究了使用 .net GZipStream 类(或 DeflateStream).但是我发现解压并不总是成功,有时图像可以解压得很好,有时我会收到 GDI+ 错误,表明某些东西已损坏.
I was in need of a way to compress images in .net so i looked into using the .net GZipStream class (or DeflateStream). However i found that decompression was not always successful, sometimes the images would decompress fine and other times i would get a GDI+ error that something is corrupted.
在调查这个问题后,我发现解压没有返回它压缩的所有字节.所以如果我压缩了 2257974 个字节,我有时只会得到 2257870 个字节(实数).
After investigating the issue i found that the decompression was not giving back all the bytes it compressed. So if i compressed 2257974 bytes i would sometimes get back only 2257870 bytes (real numbers).
最有趣的是有时它会起作用.所以我创建了这个只压缩 10 个字节的小测试方法,现在我什么也没有得到.
The most funny thing is that sometimes it would work. So i created this little test method that compresses only 10 bytes and now i don't get back anything at all.
我用 GZipStream 和 DeflateStream 两种压缩类都尝试过,我仔细检查了我的代码是否有可能的错误.我什至尝试将流定位到 0 并刷新所有流,但没有运气.
I tried it with both compression classes GZipStream and DeflateStream and i double checked my code for possible errors. I even tried positioning the stream to 0 and flushing all the streams but with no luck.
这是我的代码:
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()
).
You need to Close()
the ZipStream
after adding all the data you want to compress; it retains a buffer of unwritten bytes internally (even if you Flush()
) that needs to be written.
更一般地说,Stream
是 IDisposable
,所以你也应该 using
每个......(是的,我知道 MemoryStream
不会丢失任何数据,但如果你不养成这个习惯,它会被其他 Stream
咬你.
More generally, Stream
is IDisposable
, so you should also be using
each... (yes, I know that MemoryStream
isn't going to lose any data, but if you don't get into this habit, it will bite you with other Stream
s).
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
之类的东西——这总是一个有趣的事情,围栏两边都有很多选票:但最终......
[edit : updated re comment]
Re not using
things like MemoryStream
- this is always a fun one, with lots of votes on either side of the fence: but ultimatey...
(修辞——我们都知道答案...) MemoryStream
是如何实现的?它是一个字节 [](由 .NET 拥有)吗?它是内存映射文件(由操作系统拥有)吗?
(rhetorical - we all know the answer...) How is MemoryStream
implemented? is it a byte[] (owned by .NET)? is it a memory-mapped file (owned by the OS)?
您不使用
的原因是因为您让内部实现细节的知识改变了您针对公共 API 进行编码的方式 - 即您刚刚违反了封装定律.公共 API 说:我是 IDisposable
;你欠我的;因此,当你完成后,Dispose()
我是你的工作.
The reason you aren't using
it is because you are letting knowledge of internal implementation details change how you code against a public API - i.e. you just broke the laws of encapsulation. The public API says: I am IDisposable
; you "own" me; therefore, it is your job to Dispose()
me when you are through.
这篇关于GZipStream 和 DeflateStream 不会解压缩所有字节的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:GZipStream 和 DeflateStream 不会解压缩所有字节
基础教程推荐
- Page.OnAppearing 中的 Xamarin.Forms Page.DisplayAlert 2022-01-01
- 覆盖 Json.Net 中的默认原始类型处理 2022-01-01
- 从 VB6 迁移到 .NET/.NET Core 的最佳策略或工具 2022-01-01
- 我什么时候应该使用 GC.SuppressFinalize()? 2022-01-01
- 如何使用OpenXML SDK将Excel转换为CSV? 2022-01-01
- 当键值未知时反序列化 JSON 2022-01-01
- C# - 如何列出发布到 ASPX 页面的变量名称和值 2022-01-01
- 创建属性设置器委托 2022-01-01
- C# - 将浮点数转换为整数...并根据余数更改整数 2022-01-01
- 使用 SED 在 XML 标签之间提取值 2022-01-01