解压缩流

4
我正在尝试使用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);
                }
            }
        }
   } 
3个回答

2

我为您写了一个快速示例,它没有执行加密,但是它标出了加密/解密应该发生的位置。这是一个 .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
你正在将压缩数据视为 utf-8 字节数组。Utf-8 实际上有非常严格的规则,因此在这一步中,你的一半压缩数据可能被问号(用于表示无效字符的占位符)替换。
你需要加密/解密原始二进制数据,并且不要进行字符串转换。压缩数据不是字符串,不应该被视为字符串处理。
如果你的加密方法只能操作字符串(我没有你的 Cryptography 类的定义),那么你别无选择,只能先加密 XML 数据,然后再压缩它(虽然这样可能无法很好地压缩)。
你实际上也没有进行任何解压缩;你为压缩数据构造了一个 MemoryStream 和 GZipStream,但然后没有对它们做任何操作,而是直接尝试使用 data。

2

您没有从“decompress”中读取任何内容。 您需要从“decompress”中读取所有数据(因为没有存储数据长度,所以必须读取到流为空),然后像您正在做的那样将其转换为字符串。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接