GZipStream和DeflateStream不会DECOM preSS的所有字节 [英] GZipStream And DeflateStream will not decompress all bytes

查看:149
本文介绍了GZipStream和DeflateStream不会DECOM preSS的所有字节的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要一种方法来在.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 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())
    { ... }
}

[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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆