2010-07-24 26 views
16

J'essaye d'écrire un décodeur pour un type de cryptage très simple. Numéros de 0 à 255 sont entrés via Scanner, les bits sont inversés, puis convertis en un caractère et imprimés.Comment puis-je inverser des bits d'un octet non signé en Java?

Par exemple, le nombre 178 doit être converti en la lettre "M".

178 est 10110010.

tous les Inversion des bits devrait donner 01.001.101, ce qui est 77 ou "M" comme un personnage.

Le principal problème que j'ai, c'est que, pour autant que je sache, Java ne supporte pas les octets non signés. Je pourrais lire les valeurs comme un int ou un court, mais ensuite les valeurs seront désactivées pendant la conversion en raison des bits supplémentaires. Idéalement, je pourrais simplement utiliser l'opérateur de complément bit à bit, mais je pense que je finirai par obtenir des valeurs négatives si je fais cela avec des nombres signés. Des idées sur comment je devrais aborder cela?

+5

Vous avez choisi un exemple vraiment mauvais, car il permet deux lectures. – starblue

+0

Le bitmask était exactement ce dont j'avais besoin - je ne savais pas que vous pouviez faire ça. Très utile. Merci à tous pour les réponses. – DavidKelly999

Répondre

0

La meilleure façon d'y parvenir est de trois étapes:

  1. lire la valeur comme un int (32 bits en Java). Il peut lire comme négatif mais nous nous intéressons seulement aux 8 derniers bits de toute façon. int i = scanner.nextByte();
  2. Est-ce que l'inversion comme un int en utilisant les opérateurs de bits (comme vous le dites vous donnera 1s en bits de poids fort: i = ~i;
  3. perdre les bits d'ordre avec un ET logique: i = i & 0xFF;

Ensuite il suffit d'utiliser le résultat comme un personnage (qui est en fait 16 bits en java, mais nous utiliserons 8 d'entre eux):

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

Tous ensemble:

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

Dans la question, il est dit "Numéros de 0-255". scanner.nextByte échouera pour les nombres supérieurs à 127. –

1

Si Java le permet, vous pouvez le lire dans un type plus grand, complimenter le bit, puis masquer par bit les bits indésirables.

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

opérations en Java sont au niveau du bit définies pour int il est donc logique de travailler avec int plutôt que byte. Vous pouvez utiliser Scanner.nextInt au lieu de Scanner.nextByte. Vous devez valider l'entrée de l'utilisateur pour vous assurer que tous les entiers entrés sont compris entre 0 et 255 et afficher un message d'erreur approprié si un nombre hors plage est rencontré. Une fois que vous avez le nombre stocké dans un nombre entier alors pour retourner les 8 bits les moins significatifs, vous pouvez XOR avec 0xff.Cela devrait fonctionner comme prévu pour toutes les entrées entre 0 et 255:

x ^= 0xff; 

Exemple:

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

Résultat:

77 
255 
0 
+0

Cela ne fonctionnera pas si la valeur d'origine est stockée dans un octet, car elle sera ensuite étendue à un nombre entier négatif. – starblue

+0

@starblue: Il semble qu'il utilise un scanner. J'ai mis à jour ma réponse pour le mentionner. –

11
~n & 0xff 

~-ce que le complément et convertit implicitement un nombre entier comme toutes les opérations numériques, puis & 0xff masque tout sauf les 8 bits inférieurs pour obtenir la valeur non signée, à nouveau sous la forme d'un entier.

j'ai lu votre question différemment, d'inverser l'ordre au lieu des valeurs des bits, et ce fut la réponse.

Vous pouvez utiliser Integer.reverse() (non testé):

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

Si quelqu'un utilise ceci, la méthode 'Integer.reverse' fonctionne parfaitement (testée)! Merci d'avance! – Squeazer

13

Je voudrais simplement utiliser les compléter et de se débarrasser des autres bits en utilisant binaire et.

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

Voici octets Java, triées par représentation binaire (00000000-11111111):

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

00000000 est 0, -1 est 11111111

Inverted 0 est -1, -2 est inversé 1, ..., 127 est inversé -128. Ainsi, si vous voulez inverser les bits de Java octet vous devez obtenir votre octet de signe opposé et soustrayez un:

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

La deuxième ligne de code ne sera pas compilée. –

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

Une explication serait vraiment bien. – awksp