He/she bumped into this problem when porting C application to Java which parses UDP packets. Sounds like Java is lacking the flexibility of C whereby it could simply copy the memory block content to a pointer of any types (including struct).
While in C/C++ it is legal to do this:
[sourcecode lang="c"]
#include
char cbuf[] = { 0, 0, 96, 64 }; /* representing single precision floating point 3.5f */
int main(int argc, char **argv) {
int i;
for(i = 0; i < 4; i++) {
printf("cbuf[%d] = %d\n", i, cbuf[i]);
}
float *fp = (float *) cbuf;
printf("*fp = %3.3f\n\n", *fp);
}
[/sourcecode]
Which prints the result:
[sourcecode lang="shell"]
cbuf[0]=0
cbuf[1]=0
cbuf[2]=96
cbuf[3]=64
res = 3.500
[/sourcecode]
You just can't do that in Java (plus you won't be getting mystifying errors due to memory stomping as well).
NOTE: because we are using C language, result might be different from platform to platform, due to Little Endian/Big Endian issue.
In order to achieve the conversion in Java, you have to parse the byte array (equivalent to char[] in above C example code).
I constructed a Java utility class named FloatByteArrayUtil:
[sourcecode lang="java"]
public class FloatByteArrayUtil {
private static final int MASK = 0xff;
/**
* convert byte array (of size 4) to float
* @param test
* @return
*/
public static float byteArrayToFloat(byte test[]) {
int bits = 0;
int i = 0;
for (int shifter = 3; shifter >= 0; shifter--) {
bits |= ((int) test[i] & MASK) << (shifter * 8);
i++;
}
return Float.intBitsToFloat(bits);
}
/**
* convert float to byte array (of size 4)
* @param f
* @return
*/
public static byte[] floatToByteArray(float f) {
int i = Float.floatToRawIntBits(f);
return intToByteArray(i);
}
/**
* convert int to byte array (of size 4)
* @param param
* @return
*/
public static byte[] intToByteArray(int param) {
byte[] result = new byte[4];
for (int i = 0; i < 4; i++) {
int offset = (result.length - 1 - i) * 8;
result[i] = (byte) ((param >>> offset) & MASK);
}
return result;
}
/**
* convert byte array to String.
* @param byteArray
* @return
*/
public static String byteArrayToString(byte[] byteArray) {
StringBuilder sb = new StringBuilder("[");
if(byteArray == null) {
throw new IllegalArgumentException("byteArray must not be null");
}
int arrayLen = byteArray.length;
for(int i = 0; i < arrayLen; i++) {
sb.append(byteArray[i]);
if(i == arrayLen - 1) {
sb.append("]");
} else{
sb.append(", ");
}
}
return sb.toString();
}
}
[/sourcecode]
One good thing about Java is, we don't have the Big Endian/Little Endian issue.
This is the sample code that shows how this utility works.
[sourcecode lang="java"]
public class SampleConversion {
public static void main(String args[]) {
float source = (float) Math.exp(1);
System.out.println("source=" + source);
byte[] second = FloatByteArrayUtil.floatToByteArray(source);
System.out.println("temporary byte array=" + FloatByteArrayUtil.byteArrayToString(second));
float third = FloatByteArrayUtil.byteArrayToFloat(second);
System.out.println("result=" + third);
}
}
[/sourcecode]
Which prints:
[sourcecode lang="shell"]
source=2.7182817
temporary byte array=[64, 45, -8, 84]
result=2.7182817
[/sourcecode]
Of course you also need to take consideration of the Little Endian/Big Endian issue when parsing the bytes passed from non-Java platform, or from native binaries (I think JNI supports the conversion seamlessly).