12

I'm trying to convert a byte[] to a float[] by putting the byte[] in a ByteBuffer, converting this to a FloatBuffer (.asFloatBuffer), and then converting this to an array.

private static float[] toFloatArray(byte[] bytes) {
    ByteBuffer buffer = ByteBuffer.wrap(bytes);
    return buffer.asFloatBuffer().array();
}

However running:

 byte[] bytes = {14,32,26,21};
          toFloatArray(bytes);

Gives me a java.lang.UnsupportedOperationException at java.nio.FloatBuffer.array(Unknown Source). I believe the documentation says that the error has something to do with the buffer not being backed by an array (???).

Anyone has an idea how to fix this, or how I SHOULD convert this array to floats?

user717572
  • 3,626
  • 7
  • 35
  • 60
  • I'm tempted to think that you should be going "deeper" and trying to get a float[] to begin with instead of a byte[]. Barring that, you could just call #getFloat() on the wrapped buffer until you run out of input. – Max Oct 27 '13 at 22:10

3 Answers3

16
    private static float[] toFloatArray(byte[] bytes) {
        ByteBuffer buffer = ByteBuffer.wrap(bytes);
        FloatBuffer fb = buffer.asFloatBuffer();

        float[] floatArray = new float[fb.limit()];
        fb.get(floatArray);


        return floatArray;
    }

ex:

     byte[] bytes = {65,-56,0,0 , 65,-56,0,0};
     float[] result = toFloatArray(bytes);   

     //print 25.0 25.0
     System.out.println(Arrays.toString(result));
Faton
  • 853
  • 1
  • 9
  • 19
2

The simple way to get a float from a byte[] array wrapped by a ByteBuffer is to use getFloat() which reads the next 4 bytes and returns the generated float. You can do this in a loop, if your byte[] contains more than 4 bytes. Note that the method throws

BufferUnderflowException - If there are fewer than four bytes remaining in this buffer

You can get it from the FloatBuffer as well

buffer.asFloatBuffer().get();

if you want but array() throws an UnsupportedOperationException if the instance's hb field is null. If you look at the source code from Oracle JDK 7, there is a comment

final float[] hb;  // Non-null only for heap buffers

If you run your code, you will notice the returned FloatBuffer is a ByteBufferAsFloatBufferB, not a HeapFloatBuffer.

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • I will try this tomorrow. But if I understand it correctly, asFloatBuffer() doesnt actually convert the type, but only changes how the byte array is interpreted? – user717572 Oct 27 '13 at 22:28
  • @user Seems like it. Javadoc states `Creates a view of this byte buffer as a float buffer.` – Sotirios Delimanolis Oct 27 '13 at 22:30
  • Yes, which is why it causes an error when you do "return ByteBuffer.wrap(bytes).asFloatBuffer().array();" because really bytes is the memory that is allocated. It can't allow a float[] and byte[] array to point to the same memory. – Tatarize May 22 '17 at 03:37
1
public static float[] toFloatArray(byte[] bytes) {
    float[] floats = new float[bytes.length/4];
    ByteBuffer.wrap(bytes).asFloatBuffer().get(floats).array();
    return floats;
}

The reason why you can't do return ByteBuffer.wrap(bytes).asFloatBuffer().array(); is that it creates a view of this byte buffer as a float buffer. Which means it's using the same memory. It's lightning fast, but needs a place to put it in memory that isn't being treated as a float[] AND byte[] hence why it can't give you the data back without new memory.

public static void convertFloatArray(byte[] bytes, float[] floats) {
    ByteBuffer.wrap(bytes).asFloatBuffer().get(floats,0,bytes.length/4);
}

It's just the class doesn't make its own memory but fiddles with the memory you give it, which is awesome, but could be confusing at times.

Tatarize
  • 10,238
  • 4
  • 58
  • 64