2

I am reading a file which is stored binaries. In python I can decode the file easily

>>> s = '0000000000A0A240'
>>> s.decode('hex')
'\x00\x00\x00\x00\x00\xa0\xa2@'
>>> import struct
>>> struct.unpack('d', s.decode('hex'))[0]
2384.0

Now I want to do the same decoding in Java, do we have anything similar?

sjakobi
  • 3,546
  • 1
  • 25
  • 43
Am1rr3zA
  • 7,115
  • 18
  • 83
  • 125

1 Answers1

7

Since those bytes are in Little-Endian order, being C code on an Intel processor, use ByteBuffer to help flip the bytes:

String s = "0000000000A0A240";
double d = ByteBuffer.allocate(8)
                     .putLong(Long.parseUnsignedLong(s, 16))
                     .flip()
                     .order(ByteOrder.LITTLE_ENDIAN)
                     .getDouble();
System.out.println(d); // prints 2384.0

Here I'm using Long.parseUnsignedLong(s, 16) as a quick way to do the decode('hex') for 8 bytes.


If data is already a byte array, do this:

byte[] b = { 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0xA0, (byte) 0xA2, 0x40 };
double d = ByteBuffer.wrap(b)
                     .order(ByteOrder.LITTLE_ENDIAN)
                     .getDouble();
System.out.println(d); // prints 2384.0

Imports for the above are:

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
Andreas
  • 154,647
  • 11
  • 152
  • 247
  • nice one, the problem is I don't have it as String I have it as a bye[], something like for (byte[] val : redis.getValues()) {....} – Am1rr3zA Feb 23 '18 at 22:55
  • @Am1rr3zA Use an IDE. It would help you with the imports. – Andreas Feb 23 '18 at 23:00
  • I simplified the creation of bytes from string a bit: `ByteBuffer.wrap(DatatypeConverter.parseHexBinary("0000000000A0A240"))`, but good catch with `LITTLE_ENDIAN` also got the result `2384.0` after applying order method. – Vladimir L. Feb 23 '18 at 23:02
  • @VladimirL. Sure it appears simpler, but using a JAXB class for hex parsing just seems sooo .... *Yuck!* .... Besides, `DatatypeConverter` is not available in Java 9 SE by default. – Andreas Feb 23 '18 at 23:08
  • @Andreas at least it's better than pull the `commons-codec` dependency into a project as most of the ppl do :) And Oracle for some reason decided that `Base64` is the only decoder/encoder that developers need. I knew that `java.xml` is deprecated, but didn't know that `javax.xml.bind` is completely removed from Java 9 JDK (SE). – Vladimir L. Feb 23 '18 at 23:17
  • 1
    @VladimirL. It's not removed, but JAXB is in the `java.xml.bind` module, which is not enabled by default. You need `--add-modules java.xml.bind` to use it, or `--add-modules java.se.ee` since it's imported with the `java.se.ee` module. That why I said "by default". – Andreas Feb 23 '18 at 23:25
  • Yeah, thanks for clarification! I noticed the module graph picture in [JDK docs](https://docs.oracle.com/javase/9/docs/api/java.xml.bind-summary.html) and also read [Warning](https://stackoverflow.com/a/5942951/2288384) in the other answer about Java 9, but "in short" the shortcut with `DatatypeConverter` will be (or is already) useless with Java 9 and no strait replacement, so sad. – Vladimir L. Feb 23 '18 at 23:31
  • @VladimirL. Yeah, agreed, so sad that Java doesn't come with Hex to `byte[]` and `byte[]` to hex converters. Why is such a simple and common function missing? – Andreas Feb 23 '18 at 23:37