Reputation: 460
I took over a project that has a spec partly implemented. I have a message with various fields. One of the fields has an ID (called DestinationID) of type long. Within this ID, it says the first 4 bytes(let's call it left) represent something one thing and the other 4 bytes(let's call it right) represents another. Currently, it's been implemented as 2 ints. Giving that I have these 2 ints, is there a way to put it back together to get the original long value? Also, these fields are little endian, so the 2 ints are read as little endian. And when putting together I want to get a little endian long too. I've doing trial and error and below are my results so far. Please point out any errors you see. Thank you.
int left = 262388740; // 1st 4 bytes
int right = 671091961; // Rest of 4 bytes
long destinationID = ((right) << 32) | (left & 0xffffffffL); // Trying to put the 2 together to get the long value
//Expected - f9 0c 00 28 04 bc a3 0f
//Received - 28 00 0c f9 0f a3 bc 04
When I print (Long.toHexString(destinationID)
, I don't get the expected value. They seem reversed.
Upvotes: 0
Views: 68
Reputation: 2981
Try this.
int left = 0x0FA3BC04; //262388740; // 1st 4 bytes
int right = 0x28000CF9; //671091961; // Rest of 4 bytes
long destinationID = ((right & 0xFFL) << 56) | ((right & 0xFF00L) << 40) | ((right & 0xFF0000L) << 24) | ((right & 0xFF000000L) << 8) | ((left & 0xFFL) << 24) | ((left & 0xFF00L) << 8) | ((left >> 8) & 0xFF00L) | ((left >> 24) & 0xFFL);
System.out.printf("left: %08X%n", left); //left: 0FA3BC04
System.out.printf("right: %08X%n", right); //right: 28000CF9
System.out.println("Expected - f9 0c 00 28 04 bc a3 0f");
System.out.println(Long.toHexString(destinationID)); //f90c002804bca30f
Let change the value of left and right for clarity.
int left = 0x01234567; int right = 0x89ABCDEF;
((right & 0xFFL) << 56)
= filter 8 rightmost bits or 1 byte (0x00000000000000_EF
), then pad with 56 bits or 7 bytes of zeros to its right (0xEF_00000000000000
).((right & 0xFF00L) << 40)
= filter 16 rightmost bits or 2 bytes (0x000000000000_CD00
), then pad with 40 bits or 5 bytes of zeros to its right (0x00CD00_0000000000
).((right & 0xFF0000L) << 24)
= filter 24 rightmost bits or 3 bytes (0x0000000000_AB0000
), then pad with 24 bits or 3 bytes of zeros to its right (0x0000AB0000_000000
).((right & 0xFF000000L) << 8)
= filter 32 rightmost bits or 4 bytes (0x00000000_89000000
), then pad with 8 bits or 1 byte of zeros to its right (0x00000089000000_00
).((left & 0xFFL) << 24)
= filter 8 rightmost bits or 1 byte (0x00000000000000_67
), then pad with 24 bits or 3 bytes of zeros to its right (0x0000000067_000000
).((left & 0xFF00L) << 8)
= filter 16 rightmost bits or 2 bytes (0x000000000000_4500
), then pad with 8 bits or 1 byte of zeros to its right (0x00000000004500_00
).((left >> 8) & 0xFF00L)
= remove 8 rightmost bits or 1 byte from 0x01234567
to 0x00012345
, then get 16 rightmost bits or 2 bytes (0x000000000000_2300
).((left >> 24) & 0xFFL)
= remove 24 rightmost bits or 3 byte from 0x01234567
to 0x00000001
, then get 8 rightmost bits or 1 byte (0x00000000000000_01
).Bitwise OR (|
) between value is to merge them all into one.
0xEF00000000000000
0x00CD000000000000
0x0000AB0000000000
0x0000008900000000
0x0000000067000000
0x0000000000450000
0x0000000000002300
0x0000000000000001
------------------------
0xEFCDAB8967452301
------------------------
Upvotes: 0
Reputation: 201507
Your bytes are being written in LITTLE_ENDIAN. Note that f9 0c 00 28
and 28 00 0c f9
are reversed. I would prefer ByteBuffer
over direct bit-fiddling. Like,
int left = 262388740;
int right = 671091961;
ByteBuffer bb = ByteBuffer.allocate(8);
bb.putInt(left);
bb.putInt(right);
bb.order(ByteOrder.LITTLE_ENDIAN);
long r = bb.getLong(0);
System.out.println(Long.toHexString(r));
Outputs (as requested)
f90c002804bca30f
Upvotes: 1