UnsupportedOperationException with converting byte

2020-06-13 02:54发布

问题:

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?

回答1:

    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));


回答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.



回答3:

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.