2010-07-24 9 views
16

Ich versuche, einen Decoder für eine sehr einfache Art der Verschlüsselung zu schreiben. Zahlen von 0-255 werden über Scanner eingegeben, die Bits werden invertiert und dann in ein Zeichen umgewandelt und gedruckt.Wie kann ich Bits eines vorzeichenlosen Bytes in Java invertieren?

Zum Beispiel sollte die Zahl 178 in den Buchstaben "M" konvertieren.

178 ist 10110010.

alle Bits invertieren sollte 01001101 geben, die 77 oder "M" als ein Zeichen ist.

Das Hauptproblem, das ich habe, ist, dass, soweit ich sagen kann, Java nicht vorzeichenlose Bytes unterstützt. Ich konnte Werte als ein int oder ein kurzes lesen, aber dann werden die Werte während der Konvertierung aufgrund der zusätzlichen Bits deaktiviert. Idealerweise könnte ich einfach den bitweisen Komplement-Operator verwenden, aber ich denke, dass ich negative Zahlen bekommen werde, wenn ich dies mit vorzeichenbehafteten Zahlen mache. Irgendwelche Ideen, wie ich das angehen sollte?

+5

Sie ein wirklich schlechtes Beispiel ausgesucht, weil es zwei Lesungen ermöglicht. – starblue

+0

Die Bitmaske war genau das, was ich brauchte - ich hatte keine Ahnung, dass Sie das tun könnten. Sehr hilfreich. Vielen Dank für die Antworten. – DavidKelly999

Antwort

0

Der einfachste Weg dies zu tun ist, drei Stufen:

  1. den Wert als int Lesen (32 Bits in Java). Es kann als negativ gelesen werden, aber wir interessieren uns sowieso nur für die unteren 8 Bits. int i = scanner.nextByte();
  2. Haben die Inversion als int bitweise Operatoren (wie Sie sagen, wird Ihnen als höherwertigen Bits 1s: i = ~i;
  3. verlieren die höherwertigen Bits mit einer logischen UND: i = i & 0xFF;

Dann benutzen Sie einfach das Ergebnis als ein Zeichen (die eigentlich 16 Bit in Java, aber wir verwenden 8 von ihnen nur):

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

Alle zusammen:

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

In der Frage heißt es "Zahlen von 0-255". scanner.nextByte wird für Zahlen größer als 127 fehlschlagen. –

1

Wenn Java dies unterstützt, könnten Sie es in einen größeren Typ, bitweises Kompliment lesen und dann die unerwünschten Bits ausblenden.

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

bitweise Operationen in Java definiert für int so macht es Sinn, mit int zu arbeiten, anstatt byte. Sie können Scanner.nextInt statt Scanner.nextByte verwenden. Sie sollten die Eingabe des Benutzers überprüfen, um sicherzustellen, dass alle eingegebenen Ganzzahlen im Bereich von 0 bis 255 liegen und eine entsprechende Fehlermeldung angezeigt wird, wenn eine außerhalb des Bereichs liegende Zahl gefunden wird.

Sobald Sie die Zahl in einer Ganzzahl gespeichert haben, können Sie die niedrigstwertigen 8 Bits umkehren, um XOR mit 0xff zu koppeln.Dies sollte funktionieren, wie Sie für alle Eingänge zwischen 0 und 255 erwarten:

x ^= 0xff; 

Beispiel:

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

Ergebnis:

77 
255 
0 
+0

Dies funktioniert nicht, wenn der Wert ursprünglich in einem Byte gespeichert wird, da dann eine Vorzeichenerweiterung auf eine negative Ganzzahl erfolgt. – starblue

+0

@starblue: Es scheint, dass er einen Scanner verwendet. Ich habe meine Antwort aktualisiert, um dies zu erwähnen. –

11
~n & 0xff 

~ tut das Komplement und implizit umwandelt eine Ganzzahl wie alle numerischen Operationen, dann blendet & 0xff alles aus außer den unteren 8 Bits, um den vorzeichenlosen Wert zu erhalten, wiederum als Ganzzahl.

Ich las zuerst Ihre Frage anders, um die Reihenfolge anstelle der Werte der Bits zu invertieren, und das war die Antwort.

können Sie verwenden Integer.reverse() (ungetestet):

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

Wenn jemand dies verwendet, funktioniert die "Integer.reverse" Methode perfekt (getestet)! Danke übrigens! – Squeazer

13

Ich würde einfach die, die verwenden ergänzen und durch binäre und mit den anderen Bits loszuwerden.

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

Hier sind Java Bytes, durch binäre Darstellung sortiert (00.000.000 bis 11.111.111):

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

00000000 0, 11111111 -1

Inverted 0 -1 ist, invertiert 1 -2, ..., invertiert 127 -128 ist. Wenn Sie also Bits von Java invertieren möchten Byte Sie Ihr Byte mit umgekehrtem Vorzeichen bekommen soll und subtrahieren:

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

Zweite Codezeile wird nicht kompiliert. –

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

Eine Erklärung wäre wirklich nett. – awksp