Чтение 64-битного float little-endian на Java
Как я могу прочитать 64-битное значение float 1504642224.94664
из шестнадцатеричного C2 95 3C 2C C1 6B D6 41
с помощью Java? Я перепробовал все предложения, которые нашел в интернете, и, похоже, ничто не возвращает ожидаемое значение.
В настоящее время я использую Netty 4.1.24.Final
для моего кода ввода-вывода, и я бы предпочел решение как таковое. Я также использую поплавки для хранения значения, но я гибок в отношении конечного типа.
ByteBuf buffer = Unpooled.copiedBuffer( IO.decodeHex( "C2953C2CC16BD641" ) );
buffer.readBytes( 8 ).order( ByteOrder.LITTLE_ENDIAN ).readFloat()
Это решение когда-то работало, но таинственным образом оно перестало работать после обновления Java и Netty - возможно, оно никогда не работало а я просто забыл. Кроме того, Нетти отвергла метод order()
в пользу метода readFloatLE()
, который также не работает.
Как вы можете видеть, я получил шестнадцатеричный редактор Bless для отображения правильного значения, поэтому должно быть решение. Бонусные очки: каким было бы обратное решение, чтобы записать это значение обратно в 64-битный float?
2 ответа:
Я считаю, что вы просто неправильно определили свое шестнадцатеричное значение и используете неправильный тип.
Это работает для меня
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;
Вы можете попробовать это, сделав:
ByteBuf hex = Unpooled.buffer(8).order(ByteOrder.LITTLE_ENDIAN); hex.writeLong(Double.doubleToLongBits(1504642224.94664)); System.out.println(ByteBufUtil.prettyHexDump(hex));
Который дает
C0 95 3C 2C C1 6B D6 41
.
Я думаю, что вы должны учитывать тот факт, что вы хотите прочитать
double
, но Вы читаете его какfloat
, поэтому используются только 4 байта, так как в Java afloat
- это 4 байта.Вы должны сделать это вместо:
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);
Мое решение заключается в использовании JDK native
ByteBuffer
, но я вижу, что также ByteBuf имеет
getDouble(int index)
Возвращает 64-разрядное число с плавающей запятой в указанном абсолютном индексе в этом буфере.