2

我的最终目标是使用 protobuf-net 和 GZipStream 来尝试压缩List<MyCustomType>对象以存储在 SQL Server 的 varbinary(max) 字段中。我正在进行单元测试,以了解一切如何工作和组合在一起。

目标 .NET 框架是 3.5。

我目前的流程是:

  1. 使用 protobuf-net 序列化数据(好)。
  2. 使用 GZipStream 压缩来自 #1 的序列化数据(好)。
  3. 将压缩数据转换为 base64 字符串(好)。

此时,来自第 3 步的值将存储在 varbinary(max) 字段中。我无法控制这一点。这些步骤需要采用 base64 字符串并将其反序列化为具体类型。

  1. 将 base 64 字符串转换为byte[](好)。
  2. 使用 GZipStream 解压缩数据(好)。
  3. 使用 protobuf-net 反序列化数据(坏)。

有人可以协助为什么调用Serializer.Deserialize<string>返回null吗?我坚持这一点,希望一组新的眼睛会有所帮助。

FWIW,我尝试了另一个版本,List<T>其中 T 是我创建的自定义类,但我Deserialize<>仍然返回 null。

FWIW 2,data.txt 是一个 4MB 的纯文本文件,位于我的 C: 上。

    [Test]
    public void ForStackOverflow()
    {
        string data = "hi, my name is...";
        //string data = File.ReadAllText(@"C:\Temp\data.txt");

        string serializedBase64;

        using (MemoryStream protobuf = new MemoryStream())
        {
            Serializer.Serialize(protobuf, data);

            using (MemoryStream compressed = new MemoryStream())
            {
                using (GZipStream gzip = new GZipStream(compressed, CompressionMode.Compress))
                {
                    byte[] s = protobuf.ToArray();
                    gzip.Write(s, 0, s.Length);
                    gzip.Close();
                }

                serializedBase64 = Convert.ToBase64String(compressed.ToArray());
            }
        }

        byte[] base64byteArray = Convert.FromBase64String(serializedBase64);

        using (MemoryStream base64Stream = new MemoryStream(base64byteArray))
        {
            using (GZipStream gzip = new GZipStream(base64Stream, CompressionMode.Decompress))
            {
                using (MemoryStream plainText = new MemoryStream())
                {
                    byte[] buffer = new byte[4096];
                    int read;

                    while ((read = gzip.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        plainText.Write(buffer, 0, read);
                    }

                    // why does this call to Deserialize return null?
                    string deserialized = Serializer.Deserialize<string>(plainText);

                    Assert.IsNotNull(deserialized);
                    Assert.AreEqual(data, deserialized);
                }
            }
        }
    }
4

1 回答 1

4

plainText因为你写完后没有倒带。实际上,整个过程Stream是不必要的——这行得通:

using (MemoryStream base64Stream = new MemoryStream(base64byteArray))
{
    using (GZipStream gzip = new GZipStream(
        base64Stream, CompressionMode.Decompress))
    {
        string deserialized = Serializer.Deserialize<string>(gzip);

        Assert.IsNotNull(deserialized);
        Assert.AreEqual(data, deserialized);
    }
}

同样,这应该适用于序列化:

using (MemoryStream compressed = new MemoryStream())
{
    using (GZipStream gzip = new GZipStream(
        compressed, CompressionMode.Compress, true))
    {
        Serializer.Serialize(gzip, data);
    }

    serializedBase64 = Convert.ToBase64String(
        compressed.GetBuffer(), 0, (int)compressed.Length);
}
于 2013-11-08T21:35:53.580 回答