問題描述
我需要一種在 .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 不會解壓縮所有字節的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!