Reputation: 45272
Up to now, I've been using Protocol Buffers to serialize and deserialize objects using the code-generated classes.
Now I am attempting to serialize and deserialize a single 64-bit integer. The problem is, I'm getting different results in Java and C#.
Here's how I'm doing it in 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;
}
And here's how I'm doing this in C#, using 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);
}
}
The java code converted the number 9876
to [0x94, 0x4D]
The C# code converted the number 9876
to [0x08, 0x94, 0x4D]
How do I do this so that both com.google.protobuf
and protobuf.net
produce identical outputs?
Upvotes: 3
Views: 1220
Reputation: 45272
The protobuf.net method ProtoBuf.Serializer.Serialize
forces a field header (field number=1) into the stream. That's the only way you can perform a serialization; this method invokes a number of internal methods which are not publicly available.
The solution I'm using is to change the Java code to also include a field header.
Here is my new Java code.
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();
}
The changes I've made are:
CodedOutputStream.WriteInt64NoTag
, call CodedOutputStream.WriteInt64
CodedOutputStream.ReadTag
before calling CodedOutputStream.ReadInt64
Upvotes: 2