简体   繁体   English

Java-将int转换为字节数组而不考虑符号

[英]Java - converting int to byte array without considering sign

To convert an int into a byte array, I'm using the following code: 要将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;
}

There are two things which I'm attempting to do. 我正在尝试做两件事。

1)I need to know the number of bytes (rounded up to the closes byte) of the original integer. 1)我需要知道原始整数的字节数(四舍五入为关闭字节)。 However, I don't need the additional bit that is added for the sign bit when I call the toByteArray() method. 但是,当我调用toByteArray()方法时,不需要为符号位添加的其他位。 This is the reason why I have the helper method. 这就是为什么我有辅助方法的原因。 So in this example, if I don't have the helper method, when I convert 128 to a byte array I get the length to be 2 octets because of the sign bit but I'm only expecting it to be one octet. 因此,在此示例中,如果没有辅助方法,则当我将128转换为字节数组时,由于符号位的原因,长度为2个八位位组,但我只是期望它是一个八位位组。

2)I need the positive representation of the number. 2)我需要数字的正表示。 In this example, if I attempt to print the first element in array b, I get -128. 在此示例中,如果尝试打印数组b中的第一个元素,则得到-128。 However, the numbers I will be using will be positive numbers only so what I actually want is 128. I'm limited to using a byte array. 但是,我将要使用的数字只能是正数,因此我真正想要的是128。我仅限于使用字节数组。 Is there a way to accomplish this? 有没有办法做到这一点?

Updated Post 更新的帖子

Thank you for the responses. 感谢您的回复。 I haven't found the exact answer I was looking for so I'll attempt to give more details. 我没有找到我想要的确切答案,因此我将尝试提供更多详细信息。 Ultimately, I want to write values of different types over a data output stream. 最终,我想在数据输出流上写入不同类型的值。 In this post, I'd like to clarify what happens when ints are written to a data output stream. 在本文中,我想说明将int写入数据输出流时会发生什么。 I've come across two scenarios. 我遇到了两种情况。

1) 1)

DataOutputStream os = new DataOutputStream(this.socket.getOutputStream());

byte[] b = BigInteger.valueOf(128).toByteArray();

os.write(b);

2) 2)

DataOutputStream os = new DataOutputStream(this.socket.getOutputStream());
os.write(128);

In the first scenario, when the bytes are read from a data input stream, it seems that the first element in the byte array is a 0 to represent the msb and the second element in the array contains the number -128. 在第一种情况下,当从数据输入流中读取字节时,似乎字节数组中的第一个元素为0表示msb,而数组中的第二个元素包含数字-128。 However, since the msb is 0 we would be able to determine that it is intended to be a positive number. 但是,由于msb为0,我们将能够确定它打算为正数。 In the second scenario, there is no msb and the only element present in the byte array read from the input stream is -128. 在第二种情况下,没有msb,并且从输入流读取的字节数组中存在的唯一元素是-128。 I was expecting the write() method of the data output stream to convert the int into the byte array in the same manner as the toByteArray() method does on a BigInteger object. 我期望数据输出流的write()方法以与toByteArray()方法对BigInteger对象相同的方式将int转换为字节数组。 However, this doesn't seem to be the case as the msb is not present. 但是,由于不存在msb,因此似乎并非如此。 So my question is, how in the second scenario are we supposed to know that 128 is supposed to be a positive number and not a negative one if there is no msb. 所以我的问题是,在第二种情况下,我们应该如何知道如果没有msb,则128应该是一个正数,而不是一个负数。

As you probably already know 您可能已经知道

  • In an octet, the pattern 10000000 can be interpreted as either 128 or -128, depending on the, um, outside interpretation 在一个八位位组中,根据外部解释,模式10000000可以解释为128或-128
  • Java's byte type interprets octects as values in -128...127 only. Java的byte类型仅将八位byte解释为-128 ... 127中的值。

If you are building an application in which the entire world consists of nonnegative integers only, then you could simply do all of your work under the assumption that the byte value -128 will mean 128 and -127 will mean 129 and ... and -1 will mean 255. This is certainly doable but it takes work. 如果您要构建一个应用程序,其中整个世界仅由非负整数组成,那么您可以在字节值-128表示128和-127表示129和...以及-的前提下简单地完成所有工作。 1表示255。这当然是可行的,但需要花一些工夫。

Dealing with the notion of an "unsigned byte" like this is normally done by expanding the byte into a short or int with the higher order bits all set to zero and then performing arithmetic or displaying your values. 像这样处理“无符号字节”的概念通常是通过将字节扩展为全都设置为零的shortint的高阶位,然后执行算术或显示值来完成的。 You will need to decide whether such an approach is more to your liking than just representing 128 as two octets in your array. 您将需要确定这种方法是否更符合您的喜好,而不只是在数组中将128表示为两个八位位组。

I think the following code might be sufficient. 我认为以下代码可能就足够了。

In java int is a twos-complements binary number: 在java中, int是二进制补码二进制数:

-1              = 111...111
ones complement = 000...000; + 1 =
1               = 000...001

So that about the sign bit I do not understand. 所以关于标志位我不明白。 Be it, that you could do Math.abs(n) . 就是这样,您可以执行Math.abs(n) A byte ranges from -128 to 127, but the interpretation is a matter of masking, as below. 字节的范围是-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;
}

To answer your first question—how many bytes are required to represent a nonnegative integer using an unsigned representation—consider the following functions I wrote in Common Lisp. 要回答您的第一个问题(使用无符号表示来表示非负整数需要多少字节),请考虑以下我在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+)))

These highlight the mathematical underpinnings of the problem: namely, the logarithm tells you how many powers of two (as provided by bits) it takes to dominate a given nonnegative integer, adjusted to be a step function with floor , and the number of bytes it takes to hold that number of bits again as a step function, this time adjusted with ceiling . 这些突出显示了问题的数学基础:即,对告诉您,控制给定的非负整数(被调整为带有floor的阶跃函数)需要多少次幂(由位提供),并调整了它的字节数需要再次保持该位数作为步进函数,这次用ceiling调整。

Note that the number zero is intolerable as input to a logarithm function, so we avoid it explicitly. 请注意,数字零不能作为对数函数的输入,因此我们明确避免使用它。 You may observe that the bit-length function could also be written with a slight transformation of the core expression: 您可能会注意到,也可以通过对核心表达式进行一点转换来编写bit-length函数:

(defun bit-length-alt (n)
  (check-type n (integer 0) "a nonnegative integer")
  (values (ceiling (log (1+ n) 2))))

Unfortunately, as the logarithm of one is always zero , regardless of the base, this version says that the integer zero can be represented by zero bits, which isn't the answer we want. 不幸的是,作为一个对数始终为零 ,不管是基础的,这个版本说,整零可以通过零位表示,这不是我们想要的答案。

For your second goal, you can use the functions I've defined above to allocate the required number of bytes, and incrementally set the bits you need, ignoring sign. 对于第二个目标,您可以使用上面定义的函数来分配所需的字节数,并递增设置所需的位,而忽略符号。 It's hard to tell if you're having trouble getting the proper bits set in the byte vector, or whether your problem is in interpreting the bits in way that avoids treating the high bit as a sign bit (that is, two's complement representation ). 很难说出在字节向量中设置正确的位是否遇到麻烦,或者您的问题是在解释位时避免将高位视为符号位(即二进制补码表示 )。 Please elaborate what kind of push you need to get you moving again. 请详细说明您需要什么样的推动才能使自己再次前进。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM