我想将一些数据存储到Java中的字节数组中。基本上只是数字,每个数字最多占用2个字节。
我想知道如何将整数转换为2字节长的字节数组,反之亦然。我发现有很多解决方案在使用Google搜索,但是大多数解决方案没有解释代码中会发生什么。我不了解很多变化的东西,所以我希望能得到一个基本的解释。
我想将一些数据存储到Java中的字节数组中。基本上只是数字,每个数字最多占用2个字节。
我想知道如何将整数转换为2字节长的字节数组,反之亦然。我发现有很多解决方案在使用Google搜索,但是大多数解决方案没有解释代码中会发生什么。我不了解很多变化的东西,所以我希望能得到一个基本的解释。
Answers:
使用在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 }
ByteBuffer
。
wrap
和allocate
,它们不会返回抽象类的实例ByteBuffer
。
Char
,Short
,Int
。我想我可以填充到4个字节,每次都丢弃第4个字节,但是我宁愿不这样做。
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(“每个字节都有很大的乐趣”)中描述了一个与此有趣的难题。在将字节值与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位无符号整数类型。
& 0xFF
s是不必要的。
& 0xFF
s是必需的,因为它告诉JVM将带符号的字节转换为只设置了那些位的整数。否则,字节-1(0xFF)将变成整数-1(0xFFFFFFFF)。我可能是错的,即使我不在意也不会使事情变得更清晰。
byte b = 0; b |= 0x88; System.out.println(Integer.toString(b, 16)); //Output: -78 System.out.println(Integer.toString(b & 0xFF, 16)); //Output: 88
byte
使用0xFF( int
),JVM 定投byte
,以int
与1扩展或0扩展根据位领导第一。Java中没有无符号字节,byte
s总是带符号的。
ByteBuffer.getInt()
:的文档,Reads the next four bytes at this buffer's current position
将仅解析前4个字节,这不是您想要的。
您也可以将BigInteger用于可变长度的字节。您可以根据需要将其转换为long,int或short。
new BigInteger(bytes).intValue();
或表示极性:
new BigInteger(1, bytes).intValue();
只需返回字节:
new BigInteger(bytes).toByteArray()
intValueExact
,而是intValue
一个基本的实现将是这样的:
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
)表示第一个整数,依此类推。上面的源代码以little endian格式编码整数。
我认为这是转换为int的最佳模式
public int ByteToint(Byte B){
String comb;
int out=0;
comb=B+"";
salida= Integer.parseInt(comb);
out=out+128;
return out;
}
第一个将字节转换为String
comb=B+"";
下一步将转换为int
out= Integer.parseInt(comb);
但是出于这个原因,字节的范围是-128至127,我认为最好使用范围0至255,您只需要这样做:
out=out+256;