【问题标题】:Yet another DeflateStream decompression problem (using using and memory streams)又一个 DeflateStream 解压问题(使用 using 和 memory 流)
【发布时间】:2011-09-02 00:34:03
【问题描述】:

首先,我注意到压缩对象需要更多字节,然后纯粹以二进制形式表示对象。 (228 对 166)。

其次,我似乎无法解压。

此外,由于我没有 .NET 框架的第 4 版,因此我无法使用出色的 CopyTo 功能。

最后一个 DeflateStream using 块需要做什么?

MyClass MyObj = new MyClass();
MyObj.MyProp1 = true;
MyObj.MyProp2 = "Dee";
MyClass MyObAfterSerDeser = null;
using (MemoryStream ms = new MemoryStream())
{
    BinaryFormatter bf = new BinaryFormatter();
    bf.Serialize(ms, MyObj);
    byte[] prebytes = ms.ToArray(); // length 166.
    ms.SetLength(0L); 
    using(MemoryStream tmpms = new MemoryStream())
    {
        using (DeflateStream dsc = new DeflateStream(tmpms, CompressionMode.Compress))
        {
            dsc.Write(prebytes, 0, prebytes.Length);
            tmpms.WriteTo(ms); // unforunately though, just want the # of compressed bytes.
        }
    }
    byte[] cbytes = ms.ToArray();  // length 228.  Longer than uncompressed version!
    ms.SetLength(0L);

    using (MemoryStream tmpms = new MemoryStream())
    {
        tmpms.Write(cbytes, 0, cbytes.Length);
        tmpms.Position = 0;
        using (DeflateStream dsd = new DeflateStream(tmpms, CompressionMode.Decompress))
        {
            byte[] dbytes = new byte[cbytes.Length];
            dsd.Read(dbytes, 0, dbytes.Length);
            int offset = ReadAllBytesFromStream(dsd, dbytes);  // written by Mr. Skeet.
            // dsd.Write(dbytes, 0, cbytes.Length);
            // dsd.Read(dbytes, 0, dbytes.Length);
            ms.Write(dbytes, 0, offset);
        }
    }
    MyObAfterSerDeser = (MyClass)bf.Deserialize(ms);
}

【问题讨论】:

    标签: c# .net memorystream compression deflatestream


    【解决方案1】:

    不能保证 deflate 总是会导致更小的尺寸(尽管它应该在这种情况下只使用“存储/原始/未放气”部分)。

    .NET deflate 实现(也在 GZipStream 中使用)是known to be particular bad(尽管符合)在编码小数据和/或已经压缩的数据时。有 3rd 方库,包括 DotNetZip,可以纠正 .NET BCL 中存在的这两个问题。

    当我进行放气压缩(在小块数据上)时,我有一个“放气”标志,所以我存储的流只是有时放气,这取决于放气是否“值得”。

    编码愉快。

    【讨论】:

    • 谢谢。 +1 用于解决问题 1。我有点认为它可能与被压缩的数据量小有关。不幸的是,解压步骤仍然不起作用。
    【解决方案2】:

    您可以使用已经这样的字节初始化内存流(无需写入和定位):

    里面的代码是 CopyTo 在 .NET 4.0 中所做的

    MemoryStream output = new MemoryStream();
    try
    {
       using (MemoryStream ms = new MemoryStream(cbytes))
       using (DeflateStream ds = new DeflateStream(ms, CompressionMode.Decompress, true)) {
    
        int num;
        byte[] buffer = new byte[100];
        while ((num = ds.Read(buffer, 0, buffer.Length)) != 0)
        {
            output.Write(buffer, 0, num);
        }
       }
       MyObAfterSerDeser = (MyClass)bf.Deserialize(output);
    }
    finally
    {
        output.Dispose();
    }
    

    我得到这个代码是有原因的(通知处置)我相信,我记得当我试图通过using output 处置它时它不起作用,而不是它肯定看起来更酷。

    【讨论】:

    • 我试过这个,但它抱怨输出是空的。我注意到它正在跳过 while 循环,好像 ds.Read(...) 没有做任何事情。我在旧解压缩代码所在的位置尝试了您的代码,但我不得不将您的 ms 重命名为 tmpms。无论如何,它仍然无法正常工作。有什么建议吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-21
    • 2012-04-03
    相关资源
    最近更新 更多