gpt4 book ai didi

c# - ProtoBuf 在反序列化期间损坏字节数组(添加了额外的 0)

转载 作者:太空狗 更新时间:2023-10-29 23:23:25 25 4
gpt4 key购买 nike

我正在使用 ProtoBuf.NET 序列化/反序列化某些类。我发现在反序列化时,我得到了一个损坏的 byte[](额外的 0)。在您提问之前,是的,我需要 ProtoBuf API 的 *WithLengthPrefix() 版本,因为 ProtoBuf 部分位于自定义流的开头 :)

总之,我明白了

Original object is (JSON depiction):
{"ByteArray":"M+B6q+PXNuF8P5hl","ByteArray2":"DmErxVQ2y87IypSRcfxcWA==","K":2,"V
":1.0}

Protobuf: Raw Hex (42 bytes):
29-2A-20-0A-0C-33-E0-7A-AB-E3-D7-36-E1-7C-3F-98-65-12-10-0E-61-2B-C5-54-36-CB-CE
-C8-CA-94-91-71-FC-5C-58-08-02-15-00-00-80-3F

Regenerated object is (JSON depiction):
{"ByteArray":"AAAAAAAAAAAAAAAAM+B6q+PXNuF8P5hl","ByteArray2":"DmErxVQ2y87IypSRcf
xcWA==","K":2,"V":1.0}

ByteArray 成员中的额外 AAA*A 基本上是 base64 中的十六进制 0x00。

应用逻辑类似

static void Main(string[] args)
{
var parent = new Parent();
parent.Init();

Console.WriteLine("\nOriginal object is (JSON depiction):");
Console.WriteLine(JsonConvert.SerializeObject(parent));

using (var ms = new MemoryStream())
{
Serializer.SerializeWithLengthPrefix(ms, parent, PrefixStyle.Base128);
byte[] bytes2 = ms.ToArray();
var hex2 = BitConverter.ToString(bytes2);
Console.WriteLine("\nProtobuf: Hex ({0} bytes):\n{1}", bytes2.Length, hex2);

ms.Seek(0, SeekOrigin.Begin);
var backFirst = Serializer.DeserializeWithLengthPrefix<Parent>(ms,PrefixStyle.Base128);

Console.WriteLine("\nRegenerated object is (JSON depiction):");
Console.WriteLine(JsonConvert.SerializeObject(backFirst));
}
}

DTO 类是

[DataContract]
[ProtoContract]
internal class Parent : Child
{
[DataMember(Name = "ByteArray", Order = 10)]
[ProtoMember(1)]
public byte[] ByteArray { get; set; }

[DataMember(Name = "ByteArray2", Order = 30, EmitDefaultValue = false)]
[ProtoMember(2)]
public byte[] ByteArray2 { get; set; }

public Parent()
{
ByteArray = new byte[12];
}

internal void Init(bool bindRow = false)
{
base.Init();
var rng = new RNGCryptoServiceProvider();
rng.GetBytes(ByteArray);

ByteArray2 = new byte[16];
rng.GetBytes(ByteArray2);
}
}

[DataContract]
[ProtoContract]
[ProtoInclude(5, typeof(Parent))]
public class Child
{
[DataMember(Name = "K", Order = 100)]
[ProtoMember(1)]
public Int32 K { get; set; }

[DataMember(Name = "V", Order = 110)]
[ProtoMember(2)]
public float V { get; set; }

internal void Init()
{
K = 2;
V = 1.0f;
}
}

我确实看到,当我将 ByteArray = new byte[12]Parent 构造函数移到它的 Init() 方法中时, ProtoBuf 工作正常。但是,我们有应用程序逻辑可以防止在真实版本中出现这种情况(与上面看到的 SO 缩减代码相比)。

我们是不是做错了什么或者这是 ProtoBuf 中的错误?

最佳答案

开始吧:

public Parent()
{
ByteArray = new byte[12];
}

注意:protobuf 被设计为(由 google)可追加和可合并。其中 append/merge 与“append”同义(对于列表/数组等)。

两个选项(都可以通过属性实现):

  • 禁用构造函数:[ProtoContract(SkipConstructor = true)]
  • 禁用追加:[ProtoMember(1, OverwriteList = true)]

还有其他选择,但我倾向于这些。

你说数组初始化在实际代码中是不同的,但是:我不能评论我看不到的代码。

关于c# - ProtoBuf 在反序列化期间损坏字节数组(添加了额外的 0),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17768779/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com