如何在 Java 中反转无符号字节的位?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3324707/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 22:09:48  来源:igfitidea点击:

How can I invert bits of an unsigned byte in Java?

javabyteunsignedbitscomplement

提问by DavidKelly999

I am trying to write a decoder for a very simple type of encryption. Numbers from 0-255 are entered via Scanner, the bits are inverted, and then converted to a character and printed.

我正在尝试为一种非常简单的加密类型编写解码器。0-255 之间的数字通过扫描仪输入,位被反转,然后转换为字符并打印。

For example, the number 178 should convert to the letter "M".

例如,数字 178 应转换为字母“M”。

178 is 10110010.

178 是 10110010。

Inverting all of the bits should give 01001101, which is 77 or "M" as a character.

反转所有位应给出 01001101,即 77 或“M”作为字符。

The main problem I have is that, as far as I can tell, Java does not support unsigned bytes. I could read values as an int or a short, but then the values will be off during the conversion due to the extra bits. Ideally I could just use the bitwise complement operator, but I think I will end up getting negative values if I do this with signed numbers. Any ideas on how I should approach this?

我遇到的主要问题是,据我所知,Java 不支持无符号字节。我可以将值读取为 int 或 short,但是由于额外的位,这些值将在转换过程中关闭。理想情况下,我可以只使用按位补码运算符,但我认为如果我使用有符号数执行此操作,我最终会得到负值。关于我应该如何解决这个问题的任何想法?

回答by Nick Fortescue

The easiest way to do this is three stages:

最简单的方法是三个阶段:

  1. Read the value as an int (32 bits in java). It may read as negative but we only care about the bottom 8 bits anyway. int i = scanner.nextByte();
  2. Do the inversion as an int using bitwise operators (as you say will give you 1s as high order bits: i = ~i;
  3. Lose the high order bits with a logical AND: i = i & 0xFF;
  1. 将值读取为 int(Java 中的 32 位)。它可能读为负数,但无论如何我们只关心底部的 8 位。int i = scanner.nextByte();
  2. 使用按位运算符将反转作为 int 进行(如您所说,会给您 1 作为高位: i = ~i;
  3. 使用逻辑 AND 丢失高位: i = i & 0xFF;

Then just use the result as a character (which is actually 16 bits in java, but we will only use 8 of them):

然后只需将结果用作字符(在java中实际上是16位,但我们只会使用其中的8位):

char c=(char)a;
System.out.println(c); 

All together:

全部一起:

int i = scanner.nextByte(); // change this to nextInt() depending on file format
i = ~i;
i = i & 0xFF;
char c=(char)a;
System.out.println(c); 

回答by Merlyn Morgan-Graham

If Java supports this, you could read it into a larger type, bitwise-compliment, then bit-mask out the unwanted bits.

如果 Java 支持这一点,您可以将其读入更大的类型,按位赞美,然后位屏蔽掉不需要的位。

int x = [your byte];
x = ~x & 0xFF;

回答by Mark Byers

Bitwise operations in Java are defined for intso it makes sense to work with intrather than byte. You can use Scanner.nextInt, rather than Scanner.nextByte. You should validate the user's input to ensure that all integers entered are in the range 0 to 255 and display an appropriate error message if an out-of-range number is encountered.

Java 中的按位运算是为 for 定义的,int因此使用int而不是byte. 您可以使用Scanner.nextInt, 而不是Scanner.nextByte。您应该验证用户的输入以确保输入的所有整数都在 0 到 255 的范围内,并在遇到超出范围的数字时显示相应的错误消息。

Once you have the number stored in an integer then to flip the least significant 8 bits you can XOR with 0xff. This should work as you expect for all inputs between 0 and 255:

一旦您将数字存储在整数中,然后翻转最低有效 8 位,您就可以与 0xff 进行异或。对于 0 到 255 之间的所有输入,这应该可以正常工作:

x ^= 0xff;

Example:

例子:

String input = "178 0 255";
Scanner s = new Scanner(input);
while (s.hasNextInt()) {
    int x = s.nextInt();
    if (x < 0 || x > 255) {
        System.err.println("Not in range 0-255: " + x);
    } else {
        x ^= 0xff;
        System.out.println(x);
    }
}

Result:

结果:

77
255
0

回答by starblue

~n & 0xff

~does the complement and implicitly converts to an integer like all numeric operations do, then & 0xffmasks out everything except the lower 8 bits to get the unsigned value, again as an integer.

~进行补码并像所有数字运算一样隐式转换为整数,然后& 0xff屏蔽除低 8 位之外的所有内容以获得无符号值,再次作为整数。

I first read your question differently, to invert the order instead of the values of the bits, and this was the answer.

我首先以不同的方式阅读您的问题,以反转顺序而不是位的值,这就是答案。

You can use Integer.reverse()(untested):

您可以使用Integer.reverse()(未经测试):

Integer.reverse(n << 24) & 0xff

回答by stacker

I would simply use the ones complement and get rid of the other bits by using binary and.

我会简单地使用那些补码并通过使用二进制和来摆脱其他位。

public class Conv {
    public static void main(String[] args) {
        int val = 178;
        val = ~val & 0xff;
        System.out.println((char) val);
    }
}

回答by Vlad

Here are Java bytes, sorted by binary representation (from 00000000 to 11111111):

以下是 Java 字节,按二进制表示排序(从 00000000 到 11111111):

0, 1, 2, .., 126, 127, -128, -127, .., -2, -1

0, 1, 2, .., 126, 127, -128, -127, .., -2, -1

00000000 is 0, 11111111 is -1

00000000 是 0,11111111 是 -1

Inverted 0 is -1, inverted 1 is -2, ..., inverted 127 is -128. Thus if you want to invert bits of Java byte you should get your byte with opposite sign and subtract one:

倒 0 是 -1,倒 1 是 -2,...,倒 127 是 -128。因此,如果您想反转 Java 字节的位,您应该得到具有相反符号的字节并减去一:

byte myByte = 123;
byte myInvertedByte = -myByte-1;

回答by Xkynar

private byte reverseBitsByte(byte x)
{
    int intSize = 8;

    byte y = 0;
    for (int position = intSize - 1; position >= 0; position--)
    {
        y += ((x & 1) << position);
        x >>= 1;
    }
    return y;
}