GZipStream和DeflateStream不会DECOM preSS的所有字节 [英] GZipStream And DeflateStream will not decompress all bytes
问题描述
我需要一种方法来在.NET COM preSS的图像,所以我看着使用.net GZipStream类(或DeflateStream)。然而,我发现,DECOM pression并不总是成功的,有时这些图像将DECOM preSS罚款,其他时间我会得到一个GDI +错误的东西已损坏。
调查我发现,DECOM pression没有回馈所有字节它融为一体pressed发出后。所以,如果我COM pressed 2257974字节我有时会回来只有2257870字节(实数)。
最有趣的是,有时它会工作。因此,我创建了一个COM presses只有10个字节,现在我不回来任何东西这个小测试方法。
我与两个COM pression类GZipStream和DeflateStream和我双重检查我的code为可能出现的错误尝试过。我甚至尝试流定位到0和冲洗所有流,但没有运气。
下面是我的code:
公共静态无效TestCom pression()
{
字节[]试验=新字节[] {0,1,2,3,4,5,6,7,8,9}; 字节[]结果= DECOM preSS(比较preSS(测试)); //这会失败,result.Length为0
Debug.Assert的(result.Length == test.Length);
} 公共静态的byte []的COM preSS(字节[]数据)
{
VAR COM pressedStream =新的MemoryStream();
VAR zipStream =新GZipStream(COM pressedStream,COM pressionMode.Com preSS);
zipStream.Write(数据,0,data.Length);
返回COM pressedStream.ToArray();
} 公共静态的byte [] DECOM preSS(字节[]数据)
{
VAR COM pressedStream =新的MemoryStream(数据);
VAR zipStream =新GZipStream(COM pressedStream,COM pressionMode.Decom preSS);
VAR resultStream =新的MemoryStream(); VAR缓冲=新的字节[4096];
INT读; 而((读取= zipStream.Read(缓冲液,0,buffer.Length))大于0){
resultStream.Write(缓冲,0,读);
} 返回resultStream.ToArray();
}
您需要关闭()
的 ZipStream
将所有你想要的数据,以COM preSS后;它保留写入的字节的缓冲区内(即使你同花顺()
)需要被写入。
更一般地,流
是的IDisposable
,所以你也应该使用
各...(是的,我知道,的MemoryStream
不会丢失任何数据,但如果你不进入这个习惯,会咬你与其他流
S)。
公共静态的byte []的COM preSS(字节[]数据)
{
使用(VAR COM pressedStream =新的MemoryStream())
使用(VAR zipStream =新GZipStream(COM pressedStream,COM pressionMode.Com preSS))
{
zipStream.Write(数据,0,data.Length);
zipStream.Close();
返回COM pressedStream.ToArray();
}
}公共静态的byte [] DECOM preSS(字节[]数据)
{
使用(VAR COM pressedStream =新的MemoryStream(数据))
使用(VAR zipStream =新GZipStream(COM pressedStream,COM pressionMode.Decom preSS))
使用(VAR resultStream =新的MemoryStream())
{...}
}
再没有使用
如的MemoryStream
的东西 - 这始终是一个有趣的,有很多票的篱笆两侧:但ultimatey ...
(修辞 - 我们都知道答案...)如何的MemoryStream
实施?它是一个byte [](由.NET拥有)?它是一个内存映射文件(由操作系统拥有的)?
不使用的原因
那是因为你是让内部实施细节知识改变你如何对一个公共API code - 即你刚刚分手封装的法律。公共API说:我是的IDisposable
;你欠我的;因此,它是你的工作,以的Dispose()
我当你通过。
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.
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).
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.
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.
Here is my code:
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();
}
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.
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())
{ ... }
}
[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...
(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)?
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不会DECOM preSS的所有字节的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!