0

Im attempting to decode the value of "Well-known Binary" format in Java. The following Node script does what I need

Buffer.from('A4C0A7DEBFC657C0', 'hex').readDoubleLE() // returns -95.1054608

My question is, what is the equivalent Java code? Nothing I have tried has given the same result.

See: https://en.wikipedia.org/wiki/Well-known_text_representation_of_geometry

I am running this as part of an ingest pipeline in OpenSearch, so I can't use 3rd party libraries.

mrhijack
  • 311
  • 2
  • 5

3 Answers3

2

SUGGESTION: Look here:

https://stackoverflow.com/a/8074533/421195

import java.nio.ByteBuffer;

public static byte[] toByteArray(double value) {
    byte[] bytes = new byte[8];
    ByteBuffer.wrap(bytes).putDouble(value);
    return bytes;
}

public static double toDouble(byte[] bytes) {
    return ByteBuffer.wrap(bytes).getDouble();
}

To convert your hex string to a byte array, try this:

https://stackoverflow.com/a/140861/421195

Java 17 now includes java.util.HexFormat (only took 25 years):

HexFormat.of().parseHex(s)

For older versions of Java: Here's a solution that I think is better than any posted so far:

/* s must be an even-length string. */
public static byte[] hexStringToByteArray(String s) {
    int len = s.length();
    byte[] data = new byte[len / 2];
    for (int i = 0; i < len; i += 2) {
        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                             + Character.digit(s.charAt(i+1), 16));
    }
    return data;
}
paulsm4
  • 114,292
  • 17
  • 138
  • 190
2

This will do it. The FP64 number you are giving is LITTLE_ENDIAN. See Endianness

public double convertFP64(String fp64) {
    return ByteBuffer
            .wrap(hexStringToByteArray(fp64))
            .order(ByteOrder.LITTLE_ENDIAN)
            .getDouble();
}
public byte[] hexStringToByteArray(String hex) {
    int l = hex.length();
    byte[] data = new byte[l / 2];
    for (int i = 0; i < l; i += 2) {
        data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
                + Character.digit(hex.charAt(i + 1), 16));
    }
    return data;
}
K.Nicholas
  • 10,956
  • 4
  • 46
  • 66
  • Thanks, I used the hex conversion you provided. I was unable to use ByteBuffer in the Open search runtime. Adding my solution... – mrhijack Sep 25 '22 at 22:05
0

I landed on a solution that doesn't require ByteBuffer as it's not available in painless.

// convert hex string to byte array
int l = hex.length();    
byte[] data = new byte[l / 2];    
for (int i = 0; i < l; i+= 2) {        
  data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)              
    + Character.digit(hex.charAt(i + 1), 16));        
}

// convert byte array to double
long bits = 0L;
for (int i = 0; i < 8; i++) {
  bits |= (data[i] & 0xFFL) << (8 * i);
}
return Double.longBitsToDouble(bits); 
mrhijack
  • 311
  • 2
  • 5