要将int转换为字节数组,我使用以下代码:
int a = 128;
byte[] b = convertIntValueToByteArray(a);
private static byte[] convertIntValueToByteArray(int intValue){
BigInteger bigInteger = BigInteger.valueOf(intValue);
byte[] origByteArray = bigInteger.toByteArray();
byte[] noSignByteArray = new byte[bigInteger.bitLength()/8];
if(bigInteger.bitLength()%8!=0){
noSignByteArray = origByteArray;
}else{
System.arraycopy(origByteArray,1,noSignByteArray,0,noSignByteArray.length);
}
return noSignByteArray;
}
我正在尝试做两件事。
1)我需要知道原始整数的字节数(向上舍入到关闭字节)。但是,当我调用toByteArray()方法时,我不需要为符号位添加额外的位。这就是为什么我有辅助方法的原因。所以在这个例子中,如果我没有辅助方法,当我将128转换为字节数组时,由于符号位,我得到的长度为2个八位字节,但我只期望它是一个八位字节。
2)我需要数字的正面表示。在这个例子中,如果我尝试打印数组b中的第一个元素,我得到-128。但是,我将使用的数字只是正数,所以我真正想要的是128.我只能使用字节数组。有没有办法实现这个目标?
更新帖子
感谢您的回复。我还没有找到我正在寻找的确切答案,所以我会尝试提供更多细节。最后,我想在数据输出流上写入不同类型的值。在这篇文章中,我想澄清一下将int写入数据输出流时会发生什么。我遇到过两种情况。
1)
DataOutputStream os = new DataOutputStream(this.socket.getOutputStream());
byte[] b = BigInteger.valueOf(128).toByteArray();
os.write(b);
2)
DataOutputStream os = new DataOutputStream(this.socket.getOutputStream());
os.write(128);
在第一种情况下,当从数据输入流中读取字节时,似乎字节数组中的第一个元素是0表示msb,而数组中的第二个元素包含数字-128。但是,由于msb为0,我们可以确定它是一个正数。在第二种情况下,没有msb,从输入流中读取的字节数组中唯一存在的元素是-128。我期望数据输出流的write()方法将int转换为字节数组,方法与toByteArray()方法在BigInteger对象上的方式相同。但是,由于msb不存在,情况似乎并非如此。所以我的问题是,在第二种情况下,如果没有msb,我们应该知道128应该是正数而不是负数。
答案 0 :(得分:4)
你可能已经知道了
10000000
可以解释为128或-128,具体取决于嗯,外部解释byte
类型将octects解释为-128 ... 127中的值。如果你正在构建一个整个世界仅由非负整数组成的应用程序,那么你可以在假设字节值-128意味着128和 - 的情况下完成所有工作。 127将意味着129和......而-1将意味着255.这肯定是可行的,但它需要工作。
处理像这样的“无符号字节”的概念通常是通过将字节扩展为short
或int
来完成的,其中高阶位全部设置为零,然后执行算术或显示你的价值观。您需要确定这种方法是否更符合您的喜好,而不仅仅是将128表示为数组中的两个八位字节。
答案 1 :(得分:2)
我认为以下代码可能就足够了。
在java中 int 是二进制补码二进制数:
-1 = 111...111
ones complement = 000...000; + 1 =
1 = 000...001
关于标志位,我不明白。是的,你可以做Math.abs(n)
。
字节的范围是-128到127,但解释是屏蔽问题,如下所示。
public static void main(String[] args) {
int n = 128;
byte[] bytes = intToFlexBytes(n);
for (byte b: bytes)
System.out.println("byte " + (((int)b) & 0xFF));
}
public static byte[] intToFlexBytes(int n) {
// Convert int to byte[4], via a ByteBuffer:
byte[] bytes = new byte[4];
ByteBuffer bb = ByteBuffer.allocateDirect(4);
bb.asIntBuffer().put(n);
bb.position(0);
bb.get(bytes);
// Leading bytes with 0:
int i = 0;
while (i < 4 && bytes[i] == 0)
++i;
// Shorten bytes array if needed:
if (i != 0) {
byte[] shortenedBytes = new byte[4 - i];
for (int j = i; j < 4; ++j) {
shortenedBytes[j - i] = bytes[j]; // System.arrayCopy not needed.
}
bytes = shortenedBytes;
}
return bytes;
}
答案 2 :(得分:1)
要回答你的第一个问题 - 使用无符号表示法表示非负整数需要多少字节 - 请考虑我在Common Lisp中编写的以下函数。
(defconstant +bits-per-byte+ 8)
(defun bit-length (n)
(check-type n (integer 0) "a nonnegative integer")
(if (zerop n)
1
(1+ (floor (log n 2)))))
(defun bytes-for-bits (n)
(check-type n (integer 1) "a positive integer")
(values (ceiling n +bits-per-byte+)))
这些突出了问题的数学基础:即logarithm告诉你主导给定非负整数所需的两个幂(由比特提供),调整为一个步长函数{ {3}},以及将该位数再次保存为步进函数所需的字节数,此时间调整为floor
。
请注意,数字零作为对数函数的输入是不可容忍的,因此我们明确地避免使用它。您可能会发现bit-length
函数也可以通过对核心表达式的轻微转换来编写:
(defun bit-length-alt (n)
(check-type n (integer 0) "a nonnegative integer")
(values (ceiling (log (1+ n) 2))))
不幸的是,由于 one 的对数总是零,无论基数如何,此版本都表示整数零可以用零位表示,这不是'我们想要的答案。
为了您的第二个目标,您可以使用我上面定义的函数来分配所需的字节数,并逐步设置您需要的位,忽略符号。很难判断你是否在获取字节向量中设置的正确位时遇到问题,或者你的问题是否在解释这些位中避免将高位视为符号位(是,二的补码表示)。请详细说明你需要什么样的推动才能让你再次活动。