我需要一种在 .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 Streams).
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 不会解压缩所有字节的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持html5模板网!
右键单击 Silverlight 4 应用程序中的列表框Right-click on a Listbox in a Silverlight 4 app(右键单击 Silverlight 4 应用程序中的列表框)
WPF c# webbrowser 在顶部菜单上滚动WPF c# webbrowser scrolls over top menu(WPF c# webbrowser 在顶部菜单上滚动)
C# 控制台应用程序 - 如何制作交互式菜单?C# Console app - How do I make an interactive menu?(C# 控制台应用程序 - 如何制作交互式菜单?)
如何避免在 .NET Windows Forms 中创建重复的表单?How to avoid duplicate form creation in .NET Windows Forms?(如何避免在 .NET Windows Forms 中创建重复的表单?)
UI自动化控制桌面应用程序并单击菜单条UI Automation Control Desktop Application and Click on Menu Strip(UI自动化控制桌面应用程序并单击菜单条)
删除菜单项周围的细边框Removing thin border around the menuitems(删除菜单项周围的细边框)