简体   繁体   English

使用protobuf为c#反序列化“long”字符串对我来说无法正常工作

[英]deserialize “long” string with protobuf for c# doesn't work properly for me

I'm obviously doing something basic wrong but I can't figure it out and don't find documentation. 我显然做了一些基本的错误,但我无法弄明白,也找不到文档。

I'm experimenting with proto-buf for .NET by Marc Gravell, and trying to serialize and deserialize objects. 我正在尝试使用Marc Gravell的.NET for proto-buf,并尝试序列化和反序列化对象。 Once an object contains a string which is "too long" (didn't try to pinpoint the size threshold but it's few hundred bytes) the string doesn't deserialize properly for me. 一旦一个对象包含一个“太长”的字符串(没有试图确定大小阈值,但它只有几百个字节),字符串不会为我正确反序列化。

This is my code: 这是我的代码:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using ProtoBuf;

namespace ConsoleApplication1
{
public class Program
{
    [ProtoContract]
    public class test
    {
        [ProtoMember(1)]            
        public int i;
        [ProtoMember(2)]
        public string s1;
        [ProtoMember(3)]
        public string s2;
        [ProtoMember(4)]
        public char[] arrchars;
        [ProtoMember(5)]
        public Dictionary<int, string> Dict = new Dictionary<int, string>();

    }


    static void Main(string[] args)
    {
        test var1 = new test();
        var1.i = 10;
        var1.s1 = "Hello";
        var1.arrchars = new char[] {'A', 'B', 'C'};
        var1.Dict.Add(10, "ten");
        var1.Dict.Add(5, "five");
        var1.s2 = new String('X', 520);

        string s = PBSerializer.Serialize(typeof (test), var1);

        test var2 = null;
        PBSerializer.Deserialize(s, out var2);
    }


    public static class PBSerializer
    {
        public static string Serialize(Type objType, object obj)
        {
            MemoryStream stream = new MemoryStream();
            ProtoBuf.Serializer.Serialize(stream, obj);
            // ProtoBuf.Serializer.SerializeWithLengthPrefix(stream, obj, PrefixStyle.Fixed32, 1);
            stream.Flush();
            stream.Position = 0;
            StreamReader sr = new StreamReader(stream);
            string res = sr.ReadToEnd();
            stream.Dispose();
            sr.Dispose();
            return res;
        }

        public static void Deserialize(string serializedObj, out test obj)
        {
            MemoryStream stream = new MemoryStream(Encoding.ASCII.GetBytes(serializedObj));
            obj = ProtoBuf.Serializer.Deserialize<test>(stream);
            // obj = ProtoBuf.Serializer.DeserializeWithLengthPrefix<test>(stream, PrefixStyle.Fixed32, 1);
            stream.Dispose();
        }

    }

}
}

var2.s2 is not identical to var1.s2 - it has an extra character at the beginning of the string and truncates the majority of the end of the string. var2.s2与var1.s2不同 - 它在字符串的开头有一个额外的字符,并截断字符串结尾的大部分。 If however, I change the length of var1.s2 to a small number (say 52 instead of 520 chars) my problem goes away but I need to be able to serialize long strings. 但是,如果我将var1.s2的长度更改为一个较小的数字(比如52而不是520个字符),我的问题就会消失,但我需要能够序列化长字符串。 I assume it has to do with something I do wrong with the setting the PrefixStyle (?) or perhaps I'm not using the right encoding (?). 我假设它与设置PrefixStyle(?)的错误有关,或者我可能没有使用正确的编码(?)。 However, trial and error didn't help me sort it out. 但是,反复试验并没有帮助我解决问题。

I'm using .NET 3.5 and tried it with versions 444 & 450 with the same result. 我正在使用.NET 3.5并尝试使用版本444和450,结果相同。

Thanks. 谢谢。

You're serializing binary data - but then trying to read it as if it were text. 您正在序列化二进制数据 - 但随后尝试将其读取为文本。 It's not - so don't do that. 它不是 - 所以不要这样做。

If you have to turn arbitrary binary data into text, use Convert.ToBase64String and Convert.FromBase64String . 如果必须将任意二进制数据转换为文本,请使用Convert.ToBase64StringConvert.FromBase64String

public static class PBSerializer
{
    public static string Serialize(Type objType, object obj)
    {
        using (MemoryStream stream = new MemoryStream())
        {
            ProtoBuf.Serializer.Serialize(stream, obj);
            return Convert.ToBase64String(stream.ToArray());
        }
    }

    // Ideally change this to use a return value instead of an out parameter...
    public static void Deserialize(string serializedObj, out test obj)
    {
        byte[] data = Convert.FromBase64String(serializedObj);
        using (MemoryStream stream = new MemoryStream(data))
        {
            obj = ProtoBuf.Serializer.Deserialize<test>(stream);
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM