Java byte数组转有符号int

前言

最近在写Java蓝牙串口通信读取数据中,需要将读取到的十六进制数转换为16位的有符号整数,网上Google一大堆,均无果,最后在StackOverFlow上找到了答案。

问题描述

通信协议上指出需要需要解析出三个16位的int型数据,每个数据2个字节,即2个byte。
通信协议

温习一下java数据类型基础知识: byte型占1个字节,int型占4个字节,在java中没有无符号的数据类型。

下面是官方给的C#示例程序代码:
C#示例程序
虽然没学过C#,但还是可以看出处理过程:
首先从原始数据byteTemp取出有用的部分复制到raw字节数组中,也就是raw中存放需要处理的两个字节,再调用自带的数组转置函数倒转一下顺序(应该是通信协议的要求),最后关键的一步调用BitConverter.ToInt16将2个字节转成一个16位的有符号整型数据。可见C#的各种小工具类还是挺全的,唉,此处不忍心要吐槽java了…
那么问题来了,如何将2个字节的字节数组转换成有符号的整型数据呢?也就是C#自带的API: BitConverter.ToInt16(byte[] src, int startIndex)在java中应该如何手动实现呢?

查看MSDN

打开微软的官方API文档想一探究竟,结果被吓得怀疑人生了,怀疑自己到底有没有学过计算机…这究竟怎么转的啊…怎么0F00就是15,F1FF就变成-15呢,郁闷…
C#API

Google搜索

无奈,先查阅各种资料,补充了点基础知识,学到了一些基本转换。

byte转换为int

两种情况:

  1. 保持值不变,如进行数值运算,采用强制转换: int aInt = (int) aByte;
  2. 保持低位不变,高位用0填充,如编码解码操作,采用位操作: int aInt = aByte & 0xFF;

int转换为byte

直接使用强制类型转换: byte aByte = (byte) aInt; 但注意前提是int值小于255

有符号byte数组与int相互转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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)
};
}
// 任意长度
public static int toInt(byte[] bRefArr) {
int iOutcome = 0;
byte bLoop;
for (int i = 0; i < bRefArr.length; i++) {
bLoop = bRefArr[i];
iOutcome += (bLoop & 0xFF) << (8 * i);
}
return iOutcome;
}

StackOverFlow找到答案

说实话,StackOverFlow才是真正的神器啊!

Convert from 2 or 4 bytes to signed/unsigned short/int
http://stackoverflow.com/questions/10803557/convert-from-2-or-4-bytes-to-signed-unsigned-short-int

StackOverFlow
其中第一个是有符号类型的,第二个是无符号类型。
此处贴上该问题正确的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class IntegerConversion
{

public static int convertTwoBytesToInt1 (byte b1, byte b2) // signed
{

return (b2 << 8) | (b1 & 0xFF);
}

public static int convertFourBytesToInt1 (byte b1, byte b2, byte b3, byte b4)
{

return (b4 << 24) | (b3 & 0xFF) << 16 | (b2 & 0xFF) << 8 | (b1 & 0xFF);
}

public static int convertTwoBytesToInt2 (byte b1, byte b2) // unsigned
{

return (b2 & 0xFF) << 8 | (b1 & 0xFF);
}

public static long convertFourBytesToInt2 (byte b1, byte b2, byte b3, byte b4)
{

return (long) (b4 & 0xFF) << 24 | (b3 & 0xFF) << 16 | (b2 & 0xFF) << 8 | (b1 & 0xFF);
}

public static void main (String[] args)
{

byte b1 = (byte) 0xFF;
byte b2 = (byte) 0xFF;
byte b3 = (byte) 0xFF;
byte b4 = (byte) 0xFF;

System.out.printf ("%,14d%n", convertTwoBytesToInt1 (b1, b2));
System.out.printf ("%,14d%n", convertTwoBytesToInt2 (b1, b2));

System.out.printf ("%,14d%n", convertFourBytesToInt1 (b1, b2, b3, b4));
System.out.printf ("%,14d%n", convertFourBytesToInt2 (b1, b2, b3, b4));
}
}

总结

  1. 不要小看基本数据类型以及各种位运算,这些往往才真的是难点,特别是对于java这种稀缺基本数据类型小工具包的语言
  2. 不要逃避问题,善用搜索引擎,还有给StackOverFlow点个赞