2

How can I read the 64-bit float value 1504642224.94664 from the hexadecimal C2 95 3C 2C C1 6B D6 41 using Java? I've tried every suggestion I've found online and nothing seems to be returning the expected value.

I'm presently using Netty 4.1.24.Final for my IO code and I would prefer a solution as such. I'm also using floats to store the value but I'm flexible on the final type.

ByteBuf buffer = Unpooled.copiedBuffer( IO.decodeHex( "C2953C2CC16BD641" ) );
buffer.readBytes( 8 ).order( ByteOrder.LITTLE_ENDIAN ).readFloat()

This solution once worked but mysteriously it quit working after updating Java and Netty - It might have never worked and I just forgot. Also, Netty has deprecated the order() method in favor of readFloatLE() which also doesn't work.

Bless Screenshot

As you can see; I've gotten the Bless Hex Editor to display the correct value, so there has to be a solution. Bonus Points: What would be the reverse solution to write that value back to a 64-bit float?

  • Did you try this one? https://stackoverflow.com/questions/3842828/converting-little-endian-to-big-endian – Scary Wombat May 30 '18 at 02:25
  • How about http://www.java2s.com/Code/Java/Language-Basics/Utilityforbyteswappingofalljavadatatypes.htm – Scary Wombat May 30 '18 at 02:26
  • Also, I think the hex should be `C0 95 3C 2C C1 6B D6 41` for the double `1504642224.94664`. At least that's what `Long.toHexString(Double.doubleToLongBits(1504642224.94664))` seems to indicate. Not sure where you `C2` comes from then. – Edwin Dalorzo May 30 '18 at 02:42
  • I absolutely agree that the `C2` bit doesn't make a lick of sense. However, I copied it directly from a hex dump I made from the data sent to me from the remote server. Would anyone have any idea why this might be? You wouldn't believe the reverse-engineering fun I've had over the last few days. – Ms. Amelia S. Greene May 30 '18 at 03:24

2 Answers2

3

I think you should consider the fact that you want to read a double but you read it as a float, so only 4 bytes are used, since in Java a float is 4 bytes.

You should do this instead:

 ByteBuffer buf = ByteBuffer.wrap(new byte[] { (byte)0xC2, (byte)0x95, 0x3C, 0x2C, (byte)0xC1, 0x6B, (byte)0xD6, 0x41 });
 double d = buf.order(ByteOrder.LITTLE_ENDIAN).getDouble();
 System.out.printf("%f", d);

My solution is by using JDK native ByteBuffer, but I see that also ByteBuf has

getDouble(int index) Gets a 64-bit floating point number at the specified absolute index in this buffer.

Jack
  • 131,802
  • 30
  • 241
  • 343
0

I believe you just have your hex value incorrectly defined and using the wrong type.

This works for me

double source = 1504642224.94664;
ByteBuf buffer = Unpooled.copiedBuffer( Hex.decodeHex( "C0953C2CC16BD641" ) );
double dest = buffer.readBytes( 8 ).order( ByteOrder.LITTLE_ENDIAN ).readDouble();

assert Double.compare(source, dest) == 0;

You can try it by doing:

ByteBuf hex = Unpooled.buffer(8).order(ByteOrder.LITTLE_ENDIAN);
hex.writeLong(Double.doubleToLongBits(1504642224.94664));
System.out.println(ByteBufUtil.prettyHexDump(hex));

Which yields C0 95 3C 2C C1 6B D6 41.

Edwin Dalorzo
  • 76,803
  • 25
  • 144
  • 205