【问题标题】:Decompress a Stream解压缩流
【发布时间】:2011-06-24 16:37:18
【问题描述】:

我正在尝试使用 GZipStream 和 BinaryStream 解压缩流,但失败了。

你能帮帮我吗?

    public static LicenseOwnerRoot GetLicenseFromStream(Stream stream)
    {
        using (BinaryReader br = new BinaryReader(stream))
        {
            string keyCrypto = br.ReadString();
            string xmlCrypto = br.ReadString();
            string key = Cryptography.Decrypt(keyCrypto);
            string xml = Cryptography.Decrypt(key, xmlCrypto);
            byte[] data = Encoding.UTF8.GetBytes(xml.ToCharArray());

            using (MemoryStream ms = new MemoryStream(data))
            {
                using (GZipStream decompress = new GZipStream(ms, CompressionMode.Decompress))
                {
                    xml = Encoding.UTF8.GetString(data);
                    LicenseOwnerRoot root = (LicenseOwnerRoot)Utility.XmlDeserialization(typeof(LicenseOwnerRoot), xml);
                    foreach (LicenseOwnerItem loi in root.Licenses)
                        loi.Root = root;
                    return root;
                }
            }
        }
    }

那个xml是压缩加密的,所以我得先解压再解密。当我尝试阅读时,会出现以下消息:GZip 标头中的幻数不正确。我尝试了很多次来解决这个问题,但这听起来可行。 问题是:我应该如何使用'usings'以及这种方式是否正确,或者是否存在另一种方式来做我想做的事情? 使用 BinaryReader 之前必须解压吗?

其实我得做这个方法的逆操作:

    public static void GenerateLicenseStream(string key, LicenseOwnerRoot root, Stream stream)
    {
        using (BinaryWriter sw = new BinaryWriter(stream))
        {
            string xml = Utility.XmlSerialization(root);
            using (MemoryStream ms = new MemoryStream())
            {
                using (GZipStream compress = new GZipStream(ms, CompressionMode.Compress))
                {
                    byte[] data = Encoding.UTF8.GetBytes(xml.ToCharArray());
                    compress.Write(data, 0, data.Length);
                    string keyCrypto = Cryptography.Encrypt(key);
                    string xmlCrypto = Cryptography.Encrypt(key, Encoding.UTF8.GetString(ms.ToArray()));
                    sw.Write(keyCrypto);
                    sw.Write(xmlCrypto);
                }
            }
        }
   } 

【问题讨论】:

    标签: c# stream gzipstream compression


    【解决方案1】:

    我为您编写了一个快速示例,它不会进行加密,但会突出显示应该在哪里进行加密/解密。这是您可以“按原样”运行的 .NET 控制台应用程序的内容:

        static void Main(string[] args)
        {
            var content = @"someTextOrXMLContentGoesHereCanBeAnything#$&%&*(@#$^";
            var data = Encoding.UTF8.GetBytes(content.ToCharArray());
            var fs = new StreamWriter(@"c:\users\stackoverflow\desktop\sample.bin");
            using (var bw = new BinaryWriter(fs.BaseStream))
            {
                using (var ms = new MemoryStream())
                {
                    using (var compress = new GZipStream(ms, CompressionMode.Compress, true))
                    {
                        compress.Write(data, 0, data.Length);
                    }
                    // encrypt goes here
                    var compressedData = ms.ToArray();
                    Console.WriteLine(compressedData.Length); // 179
                    bw.Write(compressedData);
                }
            }
            // and the reverse...
            using (var fs2 = new StreamReader(@"c:\users\stackoverflow\desktop\sample.bin"))
            {
                using (var br = new BinaryReader(fs2.BaseStream))
                {
                    var len = (int)br.BaseStream.Length;
                    var encrypted = br.ReadBytes(len);
                    // decrypt here
                    var decrypted = encrypted; // <== new result after decryption
                    using (var ms = new MemoryStream(decrypted))
                    {
                        List<byte> bytesList = new List<byte>();
                        using (var decompress = new GZipStream(ms, CompressionMode.Decompress, true))
                        {
                            int val = decompress.ReadByte();
                            while (val > -1)
                            {
                                bytesList.Add((byte)val);
                                val = decompress.ReadByte();
                            }  
                        }
                        var final_result = new String(Encoding.UTF8.GetChars(bytesList.ToArray()));
                        Console.WriteLine(final_result);
                    }
                }
            }
    
            Console.ReadLine();
        }
    

    【讨论】:

      【解决方案2】:

      您没有从“解压缩”中读取任何内容。您需要从“解压缩”中读取所有数据(因为在流为空之前,您必须读取的数据长度不存在),然后将其转换为字符串。

      【讨论】:

        【解决方案3】:

        您将压缩数据视为 utf-8 字节数组。 Utf-8 实际上有非常严格的规则,因此在该步骤中,您的一半压缩数据可能会被问号(无效字符的占位符)替换。

        您需要加密/解密原始二进制数据,并丢失字符串转换。压缩后的数据不是字符串,不应这样处理。

        如果你的加密方法只能对字符串进行操作(我没有你Cryptography类的定义),那么你别无选择,只能先加密XML数据然后然后压缩它(虽然它可能不会那样压缩)。

        您实际上也没有进行任何减压;您为压缩数据构造了MemoryStreamGZipStream,然后不对它们做任何事情并尝试直接使用data

        【讨论】:

          猜你喜欢
          • 2021-01-19
          • 1970-01-01
          • 1970-01-01
          • 2018-07-05
          • 2012-09-16
          • 1970-01-01
          • 1970-01-01
          • 2012-11-01
          • 2014-01-01
          相关资源
          最近更新 更多