2010-07-24 30 views
16

Estoy tratando de escribir un decodificador para un tipo muy simple de encriptación. Los números de 0 a 255 se ingresan a través del escáner, los bits se invierten, y luego se convierten a un personaje y se imprimen.¿Cómo puedo invertir bits de un byte sin signo en Java?

Por ejemplo, el número 178 debe convertirse a la letra "M".

178 es 10110010.

Invirtiendo todos los bits debe dar 01001101, que es 77 o "M" como un personaje.

El principal problema que tengo es que, por lo que puedo ver, Java no admite bytes sin signo. Podría leer valores como int o short, pero luego los valores estarán desactivados durante la conversión debido a los bits adicionales. Idealmente, podría usar el operador de complemento bit a bit, pero creo que terminaré obteniendo valores negativos si hago esto con números firmados. ¿Alguna idea sobre cómo debería abordar esto?

+5

usted escogió un mal ejemplo, porque permite dos lecturas. – starblue

+0

La máscara de bits era exactamente lo que necesitaba, no tenía idea de que pudieras hacer eso. Muy útil. Gracias a todos por las respuestas. – DavidKelly999

Respuesta

0

La forma más sencilla de hacerlo es tres etapas:

  1. leer el valor como un entero (32 bits en Java). Puede leerse como negativo, pero de todos modos solo nos importan los 8 bits inferiores. int i = scanner.nextByte();
  2. hacer la inversión como un int usando operadores de bits (como usted dice le dará 1S como bits de alto orden: i = ~i;
  3. bajar de los bits de orden alto con una lógica AND: i = i & 0xFF;

Entonces sólo tiene que utilizar el resultado como un personaje (que en realidad es de 16 bits, en java, pero sólo utilizaremos 8 de ellos):

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

Todos juntos:

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); 
+0

En la pregunta dice "Números del 0-255". scanner.nextByte fallará para números mayores que 127. –

1

Si Java admite esto, puede leerlo en un tipo más grande, a modo de bitio, y luego enmascarar con bits los bits no deseados.

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

operaciones bit a bit en Java se definen para int así que tiene sentido trabajar con int en lugar de byte. Puede usar Scanner.nextInt, en lugar de Scanner.nextByte. Debe validar la entrada del usuario para asegurarse de que todos los enteros ingresados ​​estén en el rango de 0 a 255 y muestre un mensaje de error apropiado si se encuentra un número fuera de rango.

Una vez que tenga el número almacenado en un número entero, entonces para voltear los 8 bits menos significativos, puede XOR con 0xff.Esto debería funcionar como se espera para todas las entradas entre 0 y 255:

x ^= 0xff; 

Ejemplo:

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); 
    } 
} 

Resultado:

77 
255 
0 
+0

esto no funcionará si el valor originalmente se almacena en un byte, porque entonces será extendido a firmar a un entero negativo. – starblue

+0

@starblue: parece que está usando un escáner. He actualizado mi respuesta para mencionar esto. –

11
~n & 0xff 

~ hace el complemento e implícitamente se convierte en un entero como todas las operaciones numéricas, entonces & 0xff enmascara todo excepto los 8 bits inferiores para obtener el valor sin signo, de nuevo como un entero.

leí por primera vez su pregunta de otra manera, invertir el orden en lugar de los valores de los bits, y esta era la respuesta.

Puede utilizar Integer.reverse() (no probado):

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

Si alguien está usando esto, el método 'Integer.reverse' funciona perfectamente (probado)! Gracias por cierto! – Squeazer

13

Me basta con utilizar el complemento y deshacerse de los otros bits utilizando binario y.

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

Éstos son bytes de Java, ordenados por la representación binaria (de 00000000 a 11111111):

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

00000000 es 0, 11111111 es -1

Inverted 0 es -1, invertida 1 es -2, ..., invertida 127 es -128. Por lo tanto, si desea invertir bits de Java byte debe obtener su byte con signo contrario y restar uno:

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

La segunda línea de código no se compilará. –

0
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; 
} 
+0

Alguna explicación sería realmente agradable. – awksp

Cuestiones relacionadas