Java中的字节数组和Int转换

nun*_*nos 43 java

我对这两个功能有些困难:byteArrayToIntintToByteArray.

问题是,如果我使用一个来到另一个并且结果到达前者,结果会有所不同,您可以从下面的示例中看到.

我找不到代码中的错误.任何想法都非常受欢迎.谢谢.

public static void main(String[] args)
{
    int a = 123;
    byte[] aBytes = intToByteArray(a);
    int a2 = byteArrayToInt(aBytes);

    System.out.println(a);         // prints '123'
    System.out.println(aBytes);    // prints '[B@459189e1'
    System.out.println(a2);        // prints '2063597568
            System.out.println(intToByteArray(a2));  // prints '[B@459189e1'
}

public static int byteArrayToInt(byte[] b) 
{
    int value = 0;
    for (int i = 0; i < 4; i++) {
        int shift = (4 - 1 - i) * 8;
        value += (b[i] & 0x000000FF) << shift;
    }
    return value;
}

public static byte[] intToByteArray(int a)
{
    byte[] ret = new byte[4];
    ret[0] = (byte) (a & 0xFF);   
    ret[1] = (byte) ((a >> 8) & 0xFF);   
    ret[2] = (byte) ((a >> 16) & 0xFF);   
    ret[3] = (byte) ((a >> 24) & 0xFF);
    return ret;
}
Run Code Online (Sandbox Code Playgroud)

Yan*_*hon 56

你的方法应该是(类似的)

public static int byteArrayToInt(byte[] b) 
{
    return   b[3] & 0xFF |
            (b[2] & 0xFF) << 8 |
            (b[1] & 0xFF) << 16 |
            (b[0] & 0xFF) << 24;
}

public static byte[] intToByteArray(int a)
{
    return new byte[] {
        (byte) ((a >> 24) & 0xFF),
        (byte) ((a >> 16) & 0xFF),   
        (byte) ((a >> 8) & 0xFF),   
        (byte) (a & 0xFF)
    };
}
Run Code Online (Sandbox Code Playgroud)

使用以下代码测试了这些方法:

Random rand = new Random(System.currentTimeMillis());
byte[] b;
int a, v;
for (int i=0; i<10000000; i++) {
    a = rand.nextInt();
    b = intToByteArray(a);
    v = byteArrayToInt(b);
    if (a != v) {
        System.out.println("ERR! " + a + " != " + Arrays.toString(b) + " != " + v);
    }
}
System.out.println("Done!");
Run Code Online (Sandbox Code Playgroud)

  • 我有点困惑.在`intToByteArray`方法中,为什么在将每个字节转换回一个字节之前必须使用AND`0xFF`?0xFF将包括所有8位.一个字节只有8位.所以代码`&0xFF`似乎毫无意义. (2认同)
  • @WaffleStealer654:这是必需的,因为Java字节是有符号的,所以如果顶部位是打开的,那么当转换为int时,它是一个负数,在所有高位中有一位.(在我看来,Java字节被签名的事实是礼貌的,非最优的,但这就是它们的方式.) (2认同)

aro*_*oth 42

您正在交换两种方法之间的字节顺序.您已将intToByteArray(int a)低位指定为ret[0],但随后byteArrayToInt(byte[] b)分配b[0]给结果的高位.您需要反转其中一个,例如:

public static byte[] intToByteArray(int a)
{
    byte[] ret = new byte[4];
    ret[3] = (byte) (a & 0xFF);   
    ret[2] = (byte) ((a >> 8) & 0xFF);   
    ret[1] = (byte) ((a >> 16) & 0xFF);   
    ret[0] = (byte) ((a >> 24) & 0xFF);
    return ret;
}
Run Code Online (Sandbox Code Playgroud)

  • 看看`ByteBuffer类',我已经围绕它创建了一个例子. (4认同)

Maa*_*wes 41

这是很多工作:

public static int byteArrayToLeInt(byte[] b) {
    final ByteBuffer bb = ByteBuffer.wrap(b);
    bb.order(ByteOrder.LITTLE_ENDIAN);
    return bb.getInt();
}

public static byte[] leIntToByteArray(int i) {
    final ByteBuffer bb = ByteBuffer.allocate(Integer.SIZE / Byte.SIZE);
    bb.order(ByteOrder.LITTLE_ENDIAN);
    bb.putInt(i);
    return bb.array();
}
Run Code Online (Sandbox Code Playgroud)

此方法使用包中的Java ByteBufferByteOrder功能java.nio.在需要可读性的情况下,此代码应该是首选.它也应该很容易记住.

我在这里显示了Little Endian字节顺序.要创建Big Endian版本,您可以简单地省略呼叫order(ByteOrder).


在性能优先于可读性的代码中(大约快10倍):

public static int byteArrayToLeInt(byte[] encodedValue) {
    int value = (encodedValue[3] << (Byte.SIZE * 3));
    value |= (encodedValue[2] & 0xFF) << (Byte.SIZE * 2);
    value |= (encodedValue[1] & 0xFF) << (Byte.SIZE * 1);
    value |= (encodedValue[0] & 0xFF);
    return value;
}

public static byte[] leIntToByteArray(int value) {
    byte[] encodedValue = new byte[Integer.SIZE / Byte.SIZE];
    encodedValue[3] = (byte) (value >> Byte.SIZE * 3);
    encodedValue[2] = (byte) (value >> Byte.SIZE * 2);   
    encodedValue[1] = (byte) (value >> Byte.SIZE);   
    encodedValue[0] = (byte) value;
    return encodedValue;
}
Run Code Online (Sandbox Code Playgroud)

只需将字节数组索引反转为从0到3的计数,即可创建此代码的Big Endian版本.


笔记:

  • 在Java 8中,您还可以使用Integer.BYTES常量,这比常量更简洁Integer.SIZE / Byte.SIZE.

  • 一行:`byte[] result = ByteBuffer.allocate(Integer.SIZE / Byte.SIZE).order(ByteOrder.LITTLE_ENDIAN).putInt(i).array();` (2认同)

Jam*_*oms 21

您还可以将BigInteger用于可变长度字节.您可以将其转换为Long,Integer或Short,以满足您的需求.

new BigInteger(bytes).intValue();
Run Code Online (Sandbox Code Playgroud)

或表示极性:

new BigInteger(1, bytes).intValue();
Run Code Online (Sandbox Code Playgroud)

要获取字节只是:

new BigInteger(bytes).toByteArray()
Run Code Online (Sandbox Code Playgroud)

  • 优秀,简单,灵活的答案.谢谢! (2认同)