使用协议缓冲区序列化/反序列化独立整数

时间:2016-02-07 23:50:51

标签: java c# serialization protocol-buffers protobuf-net

到目前为止,我一直在使用Protocol Buffers来使用代码生成的类来序列化和反序列化对象。

现在我正在尝试序列化和反序列化单个64位整数。问题是,我在Java和C#中得到了不同的结果。

以下是我在Java中的表现....

private static byte[] convertLongToByteArray(long value) throws IOException {
    int size = CodedOutputStream.computeInt64SizeNoTag(value);
    byte[] buffer = new byte[size];
    CodedOutputStream codedOutputStream = CodedOutputStream.newInstance(buffer);
    codedOutputStream.writeInt64NoTag(value);
    codedOutputStream.flush();
    codedOutputStream.checkNoSpaceLeft();
    return buffer;
}

以下是我在C#中使用protobuf.net的方式:

public void SerializeLongValue()
{
    long n = 9876;
    byte[] memoryBuffer = null;
    using (MemoryStream destination = new MemoryStream())
    {
        ProtoBuf.Serializer.Serialize(destination, n);
        destination.Flush();
        memoryBuffer = destination.ToArray();
    }

    using (MemoryStream source = new MemoryStream(memoryBuffer))
    {
        long result = ProtoBuf.Serializer.Deserialize<long>(source);
        Assert.AreEqual(n, result);
    }
}

java代码将数字9876转换为[0x94, 0x4D]

C#代码将数字9876转换为[0x08, 0x94, 0x4D]

如何执行此操作以使com.google.protobufprotobuf.net生成相同的输出?

1 个答案:

答案 0 :(得分:2)

protobuf.net方法ProtoBuf.Serializer.Serialize强制将字段标题(字段编号= 1)放入流中。这是您执行序列化的唯一方法;此方法调用许多不公开的内部方法。

我正在使用的解决方案是将Java代码更改为包含字段标题。

这是我的新Java代码。

private static byte[] convertLongToByteArray(long value) throws IOException {
    int size = CodedOutputStream.computeTagSize(1) + CodedOutputStream.computeInt64SizeNoTag(value);
    byte[] buffer = new byte[size];
    CodedOutputStream codedOutputStream = CodedOutputStream.newInstance(buffer);
    codedOutputStream.writeInt64(1, value);
    codedOutputStream.flush();
    codedOutputStream.checkNoSpaceLeft();
    return buffer;
}

public static long convertByteArrayToLong(byte[] byteArray) throws IOException {
    CodedInputStream codedInputStream = CodedInputStream.newInstance(byteArray);
    codedInputStream.readTag();
    return codedInputStream.readInt64();
}

我所做的改变是:

  • 计算所需的缓冲区大小时,请包含标记大小
  • 而不是CodedOutputStream.WriteInt64NoTag,请致电CodedOutputStream.WriteInt64
  • 回读时,请在致电CodedOutputStream.ReadTag
  • 之前致电CodedOutputStream.ReadInt64