在 Java 中将字节数组转换为整数,反之亦然

问题描述 投票:0回答:9

我想在Java中将一些数据存储到字节数组中。基本上只是数字,每个数字最多占用 2 个字节。

我想知道如何将整数转换为 2 字节长的字节数组,反之亦然。我在谷歌上找到了很多解决方案,但大多数都没有解释代码中发生的情况。有很多我不太理解的变化的东西,所以我希望有一个基本的解释。

java types endianness
9个回答
262
投票

使用

java.nio
命名空间中找到的类,特别是
ByteBuffer
。它可以为您完成所有工作。

byte[] arr = { 0x00, 0x01 };
ByteBuffer wrapped = ByteBuffer.wrap(arr); // big-endian by default
short num = wrapped.getShort(); // 1

ByteBuffer dbuf = ByteBuffer.allocate(2);
dbuf.putShort(num);
byte[] bytes = dbuf.array(); // { 0, 1 }

158
投票
byte[] toByteArray(int value) {
     return  ByteBuffer.allocate(4).putInt(value).array();
}

byte[] toByteArray(int value) {
    return new byte[] { 
        (byte)(value >> 24),
        (byte)(value >> 16),
        (byte)(value >> 8),
        (byte)value };
}

int fromByteArray(byte[] bytes) {
     return ByteBuffer.wrap(bytes).getInt();
}
// packing an array of 4 bytes to an int, big endian, minimal parentheses
// operator precedence: <<, &, | 
// when operators of equal precedence (here bitwise OR) appear in the same expression, they are evaluated from left to right
int fromByteArray(byte[] bytes) {
     return bytes[0] << 24 | (bytes[1] & 0xFF) << 16 | (bytes[2] & 0xFF) << 8 | (bytes[3] & 0xFF);
}

// packing an array of 4 bytes to an int, big endian, clean code
int fromByteArray(byte[] bytes) {
     return ((bytes[0] & 0xFF) << 24) | 
            ((bytes[1] & 0xFF) << 16) | 
            ((bytes[2] & 0xFF) << 8 ) | 
            ((bytes[3] & 0xFF) << 0 );
}

将有符号字节打包到 int 中时,需要屏蔽每个字节,因为由于算术提升规则(在 JLS,转换和提升中描述),它被符号扩展为 32 位(而不是零扩展)。

Joshua Bloch 和 Neal Gafter 在 Java Puzzlers(“A Big Delight in Every Byte”)中描述了一个与此相关的有趣谜题。将字节值与 int 值进行比较时,该字节会被符号扩展为 int,然后将该值与另一个 int 进行比较

byte[] bytes = (…)
if (bytes[0] == 0xFF) {
   // dead code, bytes[0] is in the range [-128,127] and thus never equal to 255
}

请注意,所有数字类型在 Java 中都是有符号的,但 char 是 16 位无符号整数类型。


73
投票

您还可以使用 BigInteger 来表示可变长度字节。您可以将其转换为 long、int 或short,无论哪种都适合您的需要。

new BigInteger(bytes).intValue();

或表示极性:

new BigInteger(1, bytes).intValue();

要取回字节:

new BigInteger(bytes).toByteArray()

虽然简单,但我只是想指出,如果您在循环中运行多次,这可能会导致大量垃圾收集。根据您的用例,这可能是一个问题。


6
投票

基本的实现是这样的:

public class Test {
    public static void main(String[] args) {
        int[] input = new int[] { 0x1234, 0x5678, 0x9abc };
        byte[] output = new byte[input.length * 2];

        for (int i = 0, j = 0; i < input.length; i++, j+=2) {
            output[j] = (byte)(input[i] & 0xff);
            output[j+1] = (byte)((input[i] >> 8) & 0xff);
        }

        for (int i = 0; i < output.length; i++)
            System.out.format("%02x\n",output[i]);
    }
}

为了理解这些内容,您可以阅读这篇 WP 文章:http://en.wikipedia.org/wiki/Endianness

上面的源代码将输出

34 12 78 56 bc 9a
。前2个字节(
34 12
)代表第一个整数,依此类推。上面的源代码以小端格式对整数进行编码。


5
投票
/** length should be less than 4 (for int) **/
public long byteToInt(byte[] bytes, int length) {
        int val = 0;
        if(length>4) throw new RuntimeException("Too big to fit in int");
        for (int i = 0; i < length; i++) {
            val=val<<8;
            val=val|(bytes[i] & 0xFF);
        }
        return val;
    }

4
投票

一如既往,番石榴有你需要的东西。

从字节数组到 int:

Ints.fromBytesArray
,doc 这里

从 int 转换为字节数组:

Ints.toByteArray
,doc here


2
投票

无需使用任何外部或晦涩的库或应用按位魔法(有点难以阅读),您可以将

ByteArrayOutputStream
DataOutputStream
结合使用,将
int
写入流中,就像这样使用它的
writeInt(int)
方法:

// assuming num is of type int that we want to convert into byte[]
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
dos.writeInt(num);
byte[] intBytes = bos.toByteArray();
bos.close();

类似地,使用

ByteArrayInputStream
DataInputStream
结合使用它的
int readInt()
方法从流中读取 int:

// assuming byteArr is of type byte[] that contains a number we need to read
ByteArrayInputStream bis = new ByteArrayInputStream(byteArr);
DataInputStream dis = new DataInputStream(bis);
int num = dis.readInt();
bis.close();

更新:如果整数足够小,只能容纳 2 个字节,则使用 writeShortreadShort 方法而不是

writeInt
readInt
方法。


0
投票

有人要求必须从位读取,假设您必须仅读取 3 位,但您需要有符号整数,然后使用以下内容:

data is of type: java.util.BitSet

new BigInteger(data.toByteArray).intValue() << 32 - 3 >> 32 - 3

幻数

3
可以替换为您正在使用的位(不是字节)的数量。


-7
投票

我认为这是转换为 int 的最佳模式

   public int ByteToint(Byte B){
        String comb;
        int out=0;
        comb=B+"";
        salida= Integer.parseInt(comb);
        out=out+128;
        return out;
    }

首先将字节转换为字符串

comb=B+"";

下一步是转换为 int

out= Integer.parseInt(comb);

但是由于这个原因,字节的范围是-128到127,我认为最好使用范围0到255,你只需要这样做:

out=out+256;
© www.soinside.com 2019 - 2024. All rights reserved.