【问题标题】:protobuf-net deserializing: "Arithmetic operation resulted in an overflow."protobuf-net 反序列化:“算术运算导致溢出。”
【发布时间】:2014-05-27 13:35:33
【问题描述】:

我正在使用protobuf-net 对我的模型进行序列化/反序列化。

我的模型相当简单,序列化似乎一直都在工作,但是如果我稍后将特定类型添加到我的模型反序列化中似乎会失败。

我在模型中添加“int”、“long”或“DateTime”后立即收到“算术运算导致溢出”异常。

型号:

[ProtoContract]
public class MyModel
{
    [ProtoMember(1)]
    public DateTime Time { get; set; }

    [ProtoMember(2)]
    public List<string> SomeList { get; set; }

    [ProtoMember(3)]
    public string Key { get; set; }

    [ProtoMember(4)]
    public string Value { get; set; }
}

当我删除“时间”属性时,它似乎总是有效。

例外:

 at ProtoBuf.ProtoReader.TryReadUInt64VariantWithoutMoving(UInt64& value) in c:\Dev\protobuf-net\protobuf-net\ProtoReader.cs:line 375
   at ProtoBuf.ProtoReader.ReadInt64() in c:\Dev\protobuf-net\protobuf-net\ProtoReader.cs:line 357
   at ProtoBuf.BclHelpers.ReadTimeSpanTicks(ProtoReader source) in c:\Dev\protobuf-net\protobuf-net\BclHelpers.cs:line 191
   at ProtoBuf.Serializers.DateTimeSerializer.Read(Object value, ProtoReader source) in c:\Dev\protobuf-net\protobuf-net\Serializers\DateTimeSerializer.cs:line 35
   at ProtoBuf.Serializers.PropertyDecorator.Read(Object value, ProtoReader source) in c:\Dev\protobuf-net\protobuf-net\Serializers\PropertyDecorator.cs:line 77
   at ProtoBuf.Serializers.TypeSerializer.Read(Object value, ProtoReader source) in c:\Dev\protobuf-net\protobuf-net\Serializers\TypeSerializer.cs:line 230
   at ProtoBuf.Meta.TypeModel.DeserializeCore(ProtoReader reader, Type type, Object value, Boolean noAutoCreate) in c:\Dev\protobuf-net\protobuf-net\Meta\TypeModel.cs:line 700
   at ProtoBuf.Meta.TypeModel.Deserialize(Stream source, Object value, Type type, SerializationContext context) in c:\Dev\protobuf-net\protobuf-net\Meta\TypeModel.cs:line 589
   at ProtoBuf.Serializer.Deserialize[T](Stream source) in c:\Dev\protobuf-net\protobuf-net\Serializer.cs:line 77

我做错了吗?

[编辑]

private static void Main(string[] args)
        {
            var proto = new SerializeProtoTest();
            var model = new MyModel
                            {
                                Key = "abc",
                                SomeList = new List<string> { "cde" },
                                Time = DateTime.UtcNow,
                                Value = "something"
                            };
            var s = proto.Serialize(model);
            var d = proto.Deserialize<MyModel>(s);
            Console.ReadKey();
        }

        [ProtoContract]
        public class MyModel
        {
            [ProtoMember(3)]
            public string Key { get; set; }

            [ProtoMember(2)]
            public List<string> SomeList { get; set; }

            [ProtoMember(1)]
            public DateTime Time { get; set; }

            [ProtoMember(4)]
            public string Value { get; set; }
        }

        public class SerializeProtoTest
        {
            public T Deserialize<T>(string value)
            {
                using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(value)))
                {
                    return Serializer.Deserialize<T>(ms);
                }
            }

            public string Serialize<T>(T obj)
            {
                using (var ms = new MemoryStream())
                {
                    Serializer.Serialize(ms, obj);
                    var buffer = ms.ToArray();
                    return Encoding.UTF8.GetString(buffer, 0, buffer.Length);
                }
            }
        }
    }

【问题讨论】:

  • 我无法在您的课程中重现此错误。您使用的是哪个版本的protobuf-net,您在实例的属性中放入了哪些无法序列化的值?
  • protobuf-net 2.0.0.668 无论我将哪些值放入 int/Long/DateTime 反序列化总是失败。 Time=DateTime.UtcNow SomeList = new List() {"test"} Key="53498cbc88dba01e2838132b" Value="blabla"
  • @coalmee 这很奇怪 - 你确定这不是某种流损坏(很可能:编码不当)。我们可以看看你是如何序列化/反序列化的吗?或者获得更多关于序列化/反序列化之间发生了什么的上下文?也许将错误显示为重现的代码?
  • 我编辑了我的帖子以包含完整的示例以供复制。

标签: c# .net serialization deserialization protobuf-net


【解决方案1】:

来自 cmets:

最有可能:编码不当

调用它! (来自您的编辑)

return Encoding.UTF8.GetString(buffer, 0, buffer.Length);

protobuf 数据不是文本。您不能使用文本编码来获得它的文本表示 - 事实上,您正在使用这种文本编码向后,并且它在这里没有定义的行为。您已损坏数据。更大的文章(因为我经常看到这种情况)is here(第一部分)。

但是,简短的版本是:不要那样做。如果您需要 string,请改用 base-64 或类似的:

var buffer = ms.GetBuffer();
return Convert.ToBase64String(buffer, 0, (int)ms.Length);

(同样,使用Convert.FromBase64String 来反转这个过程)

但是,如果可能的话,最好避免绕过stringbyte[] 可以正常工作(即return ms.ToArray())。

【讨论】:

  • 感谢您指出这一点,这似乎正是我的问题。特别是提供的链接为我清除了很多东西!
猜你喜欢
  • 2011-05-15
  • 2011-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多