将float[]转换为byte[]再转换为float[]

11

我想要做的是将float[]转换为byte[],并通过网络以数据报包发送,然后在接收端将其转换回byte[]

我知道可以使用getBytes[]方法将float[]转换为byte[],但我不知道如何反转此过程。


这里有一个很好的回答:https://dev59.com/B2Ik5IYBdhLWcg3wDaYW#19624671 - Steven Magana-Zook
9个回答

12

我认为您想要使用ByteBuffer类,该类具有putFloatgetFloat方法。


谢谢!我想就是这个了。我有时间会试一下,然后告诉你结果。 - brain56
1
@brain56:只是想补充一下,如果你要通过网络发送这个数据,最好明确指定一个编码方式,而不是让自己处于平台默认编码的掌控之中。 - Lie Ryan
1
ByteBuffer还有asFloatBuffer()方法,以防您不想单独提取值,您可以链接方法调用:ByteBuffer.wrap(someByteArray).asFloatBuffer().array(),从byte[]转换为float[]。 - Steven Magana-Zook
@StevenMagana-Zook 你可以把那个作为答案发布。 - Dawood ibn Kareem

6

另一种方法是使用 ByteArrayOutputStream/DataOutputStream 输出内容

float fArr[] = ...;
ByteArrayOutputStream bas = new ByteArrayOutputStream();
DataOutputStream ds = new DataOutputStream(bas);
for (float f : fArr) 
    ds.writeFloat(f);
byte[] bytes = bas.toByteArray();

使用ByteArrayInputStream/DataInputStream进行输入

byte[] buffer = ...;
ByteArrayInputStream bas = new ByteArrayInputStream(buffer);
DataInputStream ds = new DataInputStream(bas);
float[] fArr = new float[buffer.length / 4];  // 4 bytes per float
for (int i = 0; i < fArr.length; i++)
{
    fArr[i] = ds.readFloat();
}

没有 writeFloat 这样的方法 - 你的代码根本无法编译。 - pzo
1
谢谢指出,我已经更新了代码,并放置了正确的适配器类。 - ricosrealm

3

这更多是为了我未来的参考而不是别的什么。

public static byte[] floatToByte(float[] input) {
    byte[] ret = new byte[input.length*4];
    for (int x = 0; x < input.length; x++) {
        ByteBuffer.wrap(ret, x*4, 4).putFloat(input[x]);
    }
    return ret;
}

public static float[] byteToFloat(byte[] input) {
    float[] ret = new float[input.length/4];
    for (int x = 0; x < input.length; x+=4) {
        ret[x/4] = ByteBuffer.wrap(input, x, 4).getFloat();
    }
    return ret;
}

可以简化为一行,例如https://dev59.com/B2Ik5IYBdhLWcg3wDaYW#44104399中的示例。

3

使用Float.floatToIntBits()将float的位值提取为整数,然后使用BigInteger.toByteArray()生成byte[]。可以使用接受byte[]参数的BigInteger构造函数来反转此过程,然后使用Float.intBitsToFloat()


2

Steven Chou的回答进行了改进

final static int BYTES_IN_FLOAT = Float.SIZE / Byte.SIZE;

public static byte[] toByteArray(float[] floatArray) {
    ByteBuffer buffer = ByteBuffer.allocate(floatArray.length * BYTES_IN_FLOAT)
    buffer.asFloatBuffer().put(floatArray);
    return buffer.array();
}


public static float[] toFloatArray(byte[] byteArray) {
    float[] result = new float[byteArray.length / BYTES_IN_FLOAT];
    ByteBuffer.wrap(byteArray).asFloatBuffer().get(result, 0, result.length);
    return result;
}

可以使用Float.BYTES代替Float.SIZE / Byte.SIZE - Mohammad Kholghi
1
Float.BYTES 仅适用于 Java 8+。对于旧版本,使用 Float.SIZE / Byte.SIZE - MA90

1
发送者:
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
// byteBuffer reused for every element in floatArray
ByteBuffer byteBuffer = ByteBuffer.allocate(4);
// go through the elements in the float array writing its
// byte equivalent  to the stream
for(float element : floatArray) {
  byteBuffer.clear();
  byteBuffer.putFloat(element)
  byteStream.write(byteBuffer.array());
}

// Logic for sending bytestream's bytes as datagram packet
// can get byte[] from steam by: byteStream.toByteArray();

接收器:

ArrayList<Float> receivedValues = new ArrayList<Float>();
ByteBuffer byteBuffer = ByteBuffer.wrap(receivedBytes);

// while there is still 4 bytes left on the byte buffer
// grab the next float and add it to the received list
int position = 0;
while(byteBuffer.capactiy - position >= 4) {
  receivedValues.add(byteBuffer.getFloat(position));
  position += 4;
}

float[] result = new float[receivedValues.count];
return receivedValues.toArray(new float[receivedValues.size()]);

0

ByteBuffer文档:https://docs.oracle.com/javase/7/docs/api/java/nio/ByteBuffer.html

final static int nbBytesInFloat = Float.SIZE / Byte.SIZE;

public static byte[] toByteArray(float[] floatArray){
    byte[] result = new byte[floatArray.length * nbBytesInFloat];
    ByteBuffer wrappedBytes = ByteBuffer.wrap(result);
    for(int i=0;i<floatArray.length;i++) {
        wrappedBytes.putFloat(floatArray[i]);
    }
    return result;
}


public static float[] toFloatArray(byte[] byteArray){
    ByteBuffer buffer = ByteBuffer.wrap(byteArray);

    float[] result = new float[byteArray.length / nbBytesInFloat];
    for(int i=0;i<result.length;i++) {
        result[i] = buffer.getFloat();
    }
    return result;
}

如果您的应用程序更加注重性能,那么您可以考虑使用这种解决方案,而无需创建太多对象:
public byte[] floatArrayToByteArray(float[] floatArray) {
    byte[] byteArray = new byte[floatArray.length * 4];
    int byteArrayIndex = 0;
    for (int i = 0; i < floatArray.length; i++) {
        int rawInt = Float.floatToRawIntBits(floatArray[i]);
        byteArray[byteArrayIndex] = (byte) (rawInt >>> 24);
        byteArray[byteArrayIndex + 1] = (byte) (rawInt >>> 16);
        byteArray[byteArrayIndex + 2] = (byte) (rawInt >>> 8);
        byteArray[byteArrayIndex + 3] = (byte) (rawInt);
        byteArrayIndex += 4;
    }
    return byteArray;
}

0

您需要在ByteBuffer的FloatBuffer中使用getFloat()和putFloat()命令。实际上,由于速度非常快,您应该肯定这样做。这对于字节操作来说是一件好事。您还可以混合和匹配数据,并根据需要进行放置和获取。所有这些都由字节缓冲区支持。因此,发送数组的常见情况是,您需要同时发送数组的大小。

public static void writeFloatArray(float[] array, OutputStream stream) throws IOException {
    ByteBuffer buffer = ByteBuffer.allocate(4 * (array.length + 1)).putInt(array.length);
    buffer.asFloatBuffer().put(array,0,array.length);
    stream.write(buffer.array());
}

你只需要确保分配足够的字节来存储缓冲区中的所有内容。写一些东西,写一些其他东西等等。理解这一点会让事情变得更容易。相反地,我们基本上做同样的事情,尽管我们需要额外的读取操作,因为我们不知道数组有多大,只知道它存在:

public static float[] readFloatArray(InputStream in) throws IOException {
    byte[] data = new byte[4];
    if (readFully(in, data) != data.length) return null;
    int length = ByteBuffer.wrap(data).getInt();
    data = new byte[length * 4];
    if (readFully(in,data) != data.length) return null;
    float[] array = new float[length];
    ByteBuffer.wrap(data).asFloatBuffer().get(array,0,array.length);
    return array;
}

而且为了完整的功能,尽管不是这部分的一部分:

public static int readFully(InputStream in, byte[] data) throws IOException {
    int offset = 0;
    int bytesRead;
    boolean read = false;
    while ((bytesRead = in.read(data, offset, data.length - offset)) != -1) {
        read = true;
        offset += bytesRead;
        if (offset >= data.length) {
            break;
        }
    }
    return (read) ? offset : -1;
}

-4

2
但这样做只能得到表示0到255之间整数的特定浮点值。一个浮点数需要4个字节,而Byte类的floatValue方法只适用于一个字节。 - Dawood ibn Kareem

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