I'm working on converting a bunch of old tab-separated MySQL database dump files into Protocol Buffers and have run into a snag. The MySQL table includes a field of type int(11) unsigned
, which I have mapped to protobuf uint32
in the .proto
file. When parsing the MySQL records and trying to convert them to a protobuf message, it's tempting to parse that field using Integer.valueOf(String)
(or Long.valueOf(String)
to avoid overflows). However, the Protocol Buffers Language Guide indicates here that in Java, uint32
s are represented using the int
datatype, but with the first bit being reinterpreted as the highest-order bit rather than as the sign bit.
So before I go write my own String
->uint32
-flavored-int
parser, I thought it was worth asking whether anyone else has already solved this particular problem. What's the correct way of converting a String
representation of MySQL int unsigned
to a Protocol Buffers uint32
in Java?
I'd try parsing as long
and then converting to int
:
int i = (int)Long.parseLong(str);
Using long
for the conversion avoids a NumberFormatException
due to an exceeded range. The subsequent narrowing conversion will drop the more significant half of the resulting bits, leaving you exactly with the representation required by the protocol buffer.
A similar conversion for uint64
using BigInteger
could probably be written as follows (untested code):
long l = (new BigInteger(str)).longValue();
This relies on an implicit truncation, just like in the above case. The documentation states:
If this
BigInteger
is too big to fit in a long, only the low-order 64 bits are returned.
If you want to convert such an int
which actually represents an uint32
to a long
with positive sign, you should make sure to clear the 32 most significant bits, as these will be filled with copies of the most significant bit of the int
value, due to the sign-extending nature of the widening conversion.
long uintValue = intValue & 0xffffffffL;