将byte[]转换为float[]时出现UnsupportedOperationException异常

12

我试图通过将byte[]放入ByteBuffer中,将其转换为FloatBuffer(.asFloatBuffer),然后将其转换为数组来将byte[]转换为float[]。

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

然而运行:

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

出现了java.lang.UnsupportedOperationException at java.nio.FloatBuffer.array(Unknown Source)的错误。

我认为文档说这个错误与缓冲区没有由数组支持有关(???)。

是否有人知道如何修复这个问题,或者我应该如何将这个数组转换为浮点数?


我倾向于认为你应该“深入”并尝试首先获取一个float[]而不是byte[]。除此之外,你可以在包装的缓冲区上调用#getFloat(),直到你用完输入。 - Max
3个回答

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

例:

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

1
有关一些解释呢? - Kamil

2
从包装在ByteBuffer中的byte[]数组获取float的简单方法是使用getFloat(),它读取下一个4个字节并返回生成的float。如果您的byte[]包含多于4个字节,则可以在循环中执行此操作。请注意,该方法会抛出BufferUnderflowException异常,如果缓冲区中剩余的字节数少于四个。您也可以从FloatBuffer中获取它。
buffer.asFloatBuffer().get();

如果你想用array(),但是如果实例的hb字段为null,它会抛出UnsupportedOperationException。如果您查看来自Oracle JDK 7的源代码,那里有一条注释。
final float[] hb;  // Non-null only for heap buffers

如果您运行代码,您会注意到返回的 FloatBuffer 是一个 ByteBufferAsFloatBufferB,而不是一个 HeapFloatBuffer


明天我会尝试这个。但如果我理解正确的话,asFloatBuffer()并不会实际转换类型,而只是改变了字节数组的解释方式? - user717572
@user 看起来是这样的。Javadoc指出“创建一个此字节缓冲区的浮点缓冲区视图。” - Sotirios Delimanolis
是的,这就是为什么当你执行“return ByteBuffer.wrap(bytes).asFloatBuffer().array();”时会导致错误,因为实际上bytes是分配的内存。它不能允许float[]和byte[]数组指向同一块内存。 - Tatarize

1
public static float[] toFloatArray(byte[] bytes) {
    float[] floats = new float[bytes.length/4];
    ByteBuffer.wrap(bytes).asFloatBuffer().get(floats).array();
    return floats;
}

你无法执行return ByteBuffer.wrap(bytes).asFloatBuffer().array();的原因是它将这个字节缓冲区视为浮点缓冲区的视图。这意味着它使用相同的内存。它非常快,但需要一个不被视为float[]和byte[]的内存空间来存放它,因此它不能在没有新内存的情况下返回数据给你。
public static void convertFloatArray(byte[] bytes, float[] floats) {
    ByteBuffer.wrap(bytes).asFloatBuffer().get(floats,0,bytes.length/4);
}

这个类只是操作你提供给它的内存,而不是自己创建内存,这很棒,但有时可能会让人感到困惑。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接