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

发布于 2024-12-07 16:08:45 字数 151 浏览 1 评论 0原文

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

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

I want to store some data into byte arrays in Java. Basically just numbers which can take up to 2 Bytes per number.

I'd like to know how I can convert an integer into a 2 byte long byte array and vice versa. I found a lot of solutions googling but most of them don't explain what happens in the code. There's a lot of shifting stuff I don't really understand so I would appreciate a basic explanation.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

请持续率性 2024-12-14 16:08:45

使用 java.lang.Class 中找到的类。 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 }

Use the classes found in the java.nio namespace, in particular, the ByteBuffer. It can do all the work for you.

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 }
如梦亦如幻 2024-12-14 16:08:45
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 位无符号整数类型之外。

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

When packing signed bytes into an int, each byte needs to be masked off because it is sign-extended to 32 bits (rather than zero-extended) due to the arithmetic promotion rule (described in JLS, Conversions and Promotions).

There's an interesting puzzle related to this described in Java Puzzlers ("A Big Delight in Every Byte") by Joshua Bloch and Neal Gafter . When comparing a byte value to an int value, the byte is sign-extended to an int and then this value is compared to the other int

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

Note that all numeric types are signed in Java with exception to char being a 16-bit unsigned integer type.

素衣风尘叹 2024-12-14 16:08:45

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

new BigInteger(bytes).intValue();

或表示极性:

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

要返回字节:

new BigInteger(bytes).toByteArray()

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

You can also use BigInteger for variable length bytes. You can convert it to long, int or short, whichever suits your needs.

new BigInteger(bytes).intValue();

or to denote polarity:

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

To get bytes back just:

new BigInteger(bytes).toByteArray()

Although simple, I just wanted to point out that if you run this many times in a loop, this could lead to a lot of garbage collection. This may be a concern depending on your use case.

孤星 2024-12-14 16:08:45

一个基本的实现是这样的:

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)表示第一个整数,依此类推。上述源代码以小端格式对整数进行编码。

A basic implementation would be something like this:

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

In order to understand things you can read this WP article: http://en.wikipedia.org/wiki/Endianness

The above source code will output 34 12 78 56 bc 9a. The first 2 bytes (34 12) represent the first integer, etc. The above source code encodes integers in little endian format.

如梦亦如幻 2024-12-14 16:08:45
/** 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;
    }
/** 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;
    }
泪眸﹌ 2024-12-14 16:08:45

通常,番石榴可以满足您的需求。

要从字节数组转换为 int:Ints.fromBytesArray,doc 此处

要从 int 转换为字节数组:Ints.toByteArray,doc 此处

As often, guava has what you need.

To go from byte array to int: Ints.fromBytesArray, doc here

To go from int to byte array: Ints.toByteArray, doc here

哽咽笑 2024-12-14 16:08:45

无需使用任何外部或晦涩的库或应用按位魔法(有点难以阅读),您可以使用 ByteArrayOutputStreamDataOutputStream使用它的 writeInt(int) 方法将 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();

类似地使用 ByteArrayInputStreamDataInputStream 使用它的 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 个字节,然后才使用 writeShort readShort 方法而不是 writeIntreadInt 方法。

Without using any external or obscure library or applying bitwise magic (bit difficult to read), you can use ByteArrayOutputStream combined with DataOutputStream to write an int into the stream like this using it's writeInt(int) method:

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

Similarly use ByteArrayInputStream combined with DataInputStream to read an int from the stream like this using it's int readInt() method:

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

Update: If integer number is small enough to be fit into 2 bytes only then use writeShort and readShort methods instead of writeInt and readInt methods.

GRAY°灰色天空 2024-12-14 16:08:45

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

data is of type: java.util.BitSet

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

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

Someone with a requirement where they have to read from bits, lets say you have to read from only 3 bits but you need signed integer then use following:

data is of type: java.util.BitSet

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

The magic number 3 can be replaced with the number of bits (not bytes) you are using.

奈何桥上唱咆哮 2024-12-14 16:08:45

我认为这是转换为 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;

i think this is a best mode to cast to int

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

first comvert byte to String

comb=B+"";

next step is comvert to a int

out= Integer.parseInt(comb);

but byte is in rage of -128 to 127 for this reasone, i think is better use rage 0 to 255 and you only need to do this:

out=out+256;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文