Ich versuche, ein signiertes Byte in ein nicht signiertes zu konvertieren. Das Problem ist, dass die Daten, die ich empfange, nicht signiert sind und Java kein vorzeichenloses Byte unterstützt. Wenn es also die Daten liest, behandelt es sie als signiert.
Ich habe versucht, es mit der folgenden Lösung zu konvertieren, die ich von Stack Overflow erhalten habe.
public static int unsignedToBytes(byte a)
{
int b = a & 0xFF;
return b;
}
Aber wenn es wieder in Byte konvertiert wird, erhalte ich die gleichen signierten Daten. Ich versuche, diese Daten als Parameter für eine Java-Funktion zu verwenden, die nur ein Byte als Parameter akzeptiert, daher kann ich keinen anderen Datentyp verwenden. Wie kann ich dieses Problem beheben?
Antworten:
Ich bin mir nicht sicher, ob ich deine Frage verstehe.
Ich habe es gerade versucht und für Byte -12 (vorzeichenbehafteter Wert) wurde die Ganzzahl 244 zurückgegeben (entspricht dem vorzeichenlosen Bytewert, wird jedoch als
int
) eingegeben :Ist es das, was du tun willst?
Java erlaubt es nicht , 244 als auszudrücken
byte
Wert, wie für C. Um positive ganze Zahlen oben ausdrückenByte.MAX_VALUE
(127) Sie haben einen anderen Integer - Typen zu verwenden, wieshort
,int
oderlong
.quelle
byte b = (byte)unsignedToBytes((byte) -12);
Versuchen Sie jetzt, bDie Tatsache, dass Grundelemente in Java signiert sind, spielt keine Rolle für die Darstellung im Speicher / Transit - ein Byte besteht lediglich aus 8 Bit, und ob Sie dies als signierten Bereich interpretieren oder nicht, liegt bei Ihnen. Es gibt keine magische Flagge, die sagt "dies ist signiert" oder "dies ist nicht signiert".
Wenn Grundelemente signiert sind, verhindert der Java-Compiler, dass Sie einem Byte einen Wert über +127 (oder unter -128) zuweisen können. Es gibt jedoch nichts, was Sie davon abhält, einen Int (oder Short) herunterzuspielen, um dies zu erreichen:
quelle
Die Java-Sprache bietet so etwas wie das
unsigned
Schlüsselwort nicht. Abyte
gemäß der Sprachspezifikation stellt einen Wert zwischen –128 - 127 dar. Wenn beispielsweise abyte
inint
Java umgewandelt wird, wird das erste Bit als Zeichen interpretiert und die Zeichenerweiterung verwendet .Abgesehen davon hindert Sie nichts daran,
byte
einfach 8 Bits anzuzeigen und diese Bits als Wert zwischen 0 und 255 zu interpretieren. Denken Sie jedoch daran, dass Sie nichts tun können, um Ihre Interpretation der Methode eines anderen aufzuzwingen. Wenn eine Methode a akzeptiertbyte
, akzeptiert diese Methode einen Wert zwischen –128 und 127, sofern nicht ausdrücklich anders angegeben.Hier sind einige nützliche Konvertierungen / Manipulationen für Ihre Bequemlichkeit:
Konvertierungen von / nach int
(Wenn Sie Java 8+ verwenden, verwenden Sie
Byte.toUnsignedInt
.)Analysieren / Formatieren
Am besten verwenden Sie die oben genannten Konvertierungen:
Arithmetik
Die 2-Komplement-Darstellung "funktioniert einfach" für Addition, Subtraktion und Multiplikation:
Die Division erfordert die manuelle Konvertierung von Operanden:
quelle
In Java gibt es keine primitiven vorzeichenlosen Bytes. Das Übliche ist, es auf einen größeren Typ zu werfen:
quelle
Ich denke, die anderen Antworten haben die Darstellung des Gedächtnisses behandelt, und wie Sie damit umgehen, hängt davon ab, wie Sie es verwenden möchten. Ich werde hinzufügen, dass Java 8 Unterstützung für den Umgang mit vorzeichenlosen Typen hinzugefügt hat . In diesem Fall könnten Sie verwenden
Byte.toUnsignedInt
quelle
Eine Randnotiz, wenn Sie es ausdrucken möchten, können Sie einfach sagen
quelle
println(b & 0xff)
ist genugWenn Sie denken, Sie suchen nach so etwas.
quelle
Adamski lieferte die beste Antwort, aber sie ist nicht ganz vollständig. Lesen Sie daher seine Antwort, da sie die Details erklärt, die ich nicht bin.
Wenn Sie eine Systemfunktion haben, für die ein vorzeichenloses Byte übergeben werden muss, können Sie ein vorzeichenbehaftetes Byte übergeben, da es automatisch als vorzeichenloses Byte behandelt wird.
Wenn eine Systemfunktion vier Bytes benötigt, z. B. 192 168 0 1 als vorzeichenlose Bytes, können Sie -64 -88 0 1 übergeben, und die Funktion funktioniert weiterhin, da sie beim Übergeben an die Funktion die Signatur aufhebt .
Es ist jedoch unwahrscheinlich, dass dieses Problem auftritt, da Systemfunktionen aus Gründen der plattformübergreifenden Kompatibilität hinter Klassen verborgen sind, obwohl einige der Lesemethoden von java.io nicht seufzende Bytes als int zurückgeben.
Wenn Sie möchten, dass dies funktioniert, schreiben Sie signierte Bytes in eine Datei und lesen Sie sie als nicht signierte Bytes zurück.
quelle
Du kannst auch:
Erläuterung:
sagen wir
a = (byte) 133;
Im Speicher wird gespeichert als: "1000 0101" (0x85 in hex)
Seine Darstellung übersetzt also vorzeichenlos = 133, signiert = -123 (als 2er-Komplement)
Wenn die Linksverschiebung 24 Bit nach links ausgeführt wird, ist das Ergebnis nun eine 4-Byte-Ganzzahl, die wie folgt dargestellt wird:
"10000101 00000000 00000000 00000000" (oder "0x85000000" in hexadezimal)
dann haben wir
und es verschiebt sich wieder um die rechten 24 Bits, füllt sich aber mit führenden Nullen. So ergibt sich:
"00000000 00000000 00000000 10000101" (oder "0x00000085" in hex)
und das ist die vorzeichenlose Darstellung, die 133 entspricht.
Wenn Sie versuchen würden zu gießen,
a = (int) a;
würde es passieren, dass die 2er-Komplementdarstellung des Bytes beibehalten und als int auch als 2er-Komplement gespeichert wird:(int) 10000101 ---> 11111111 11111111 11111111 10000101
Und das bedeutet: -123
quelle
java.lang.Byte.toUnsignedInt(byte value)
. Wenn Sie Java 8 noch nicht verwenden, aktualisieren Sie ASAP. Java 7 und früher sind am Ende der Lebensdauer.Dies unterscheidet sich nicht wesentlich von einer Funktion, die eine Ganzzahl akzeptiert, an die Sie einen Wert übergeben möchten, der größer als 2 ^ 32-1 ist.
Das klingt so, als ob es davon abhängt, wie die Funktion definiert und dokumentiert ist. Ich kann drei Möglichkeiten sehen:
Es kann explizit dokumentieren, dass die Funktion das Byte als vorzeichenlosen Wert behandelt. In diesem Fall sollte die Funktion wahrscheinlich das tun, was Sie erwarten, scheint aber falsch implementiert zu sein. Für den Ganzzahlfall würde die Funktion den Parameter wahrscheinlich als Ganzzahl ohne Vorzeichen deklarieren, für den Bytefall ist dies jedoch nicht möglich.
Es kann dokumentiert werden, dass der Wert für dieses Argument größer als (oder vielleicht gleich) Null sein muss. In diesem Fall missbrauchen Sie die Funktion (übergeben einen Parameter außerhalb des Bereichs) und erwarten, dass sie mehr tut, als sie entworfen wurde machen. Bei einem gewissen Grad an Debugging-Unterstützung können Sie erwarten, dass die Funktion eine Ausnahme auslöst oder eine Zusicherung fehlschlägt.
Die Dokumentation kann nichts sagen. In diesem Fall ist ein negativer Parameter ein negativer Parameter, und ob dies eine Bedeutung hat, hängt davon ab, was die Funktion tut. Wenn dies bedeutungslos ist, sollte die Funktion möglicherweise wirklich als (2) definiert / dokumentiert werden. Wenn dies auf nicht offensichtliche Weise sinnvoll ist (z. B. werden nicht negative Werte verwendet, um in ein Array zu indizieren, und negative Werte werden verwendet, um vom Ende des Arrays zurück zu indizieren, sodass -1 das letzte Element bedeutet), sollte in der Dokumentation angegeben werden, was es ist bedeutet und ich würde erwarten, dass es sowieso nicht das ist, was Sie wollen.
quelle
Wenn Sie eine Funktion haben, der ein vorzeichenbehaftetes Byte übergeben werden muss, was erwarten Sie dann, wenn Sie ein vorzeichenloses Byte übergeben?
Warum können Sie keinen anderen Datentyp verwenden?
Ungewöhnlich können Sie ein Byte als vorzeichenloses Byte mit einfachen oder keinen Übersetzungen verwenden. Es hängt alles davon ab, wie es verwendet wird. Sie müssten klären, was Sie damit vorhaben.
quelle
Obwohl es ärgerlich erscheinen mag (von C kommend), dass Java kein vorzeichenloses Byte in die Sprache aufgenommen hat, ist es wirklich keine große Sache, da eine einfache "b & 0xFF" -Operation den vorzeichenlosen Wert für (vorzeichenbehaftetes) Byte b im (seltenen) liefert. Situationen, die es tatsächlich benötigt. Die Bits ändern sich nicht wirklich - nur die Interpretation (was nur wichtig ist, wenn zum Beispiel einige mathematische Operationen an den Werten ausgeführt werden).
quelle
x & 0xFF
entweder überall, wo Sie es brauchen, oder Sie wiederholen so etwas wiebehaveLikeAnUnsignedByte(x)
überall. Dies ist für jede einzelne Stelle erforderlich, an der Sie einen Bytewert oder ein Byte-Array verwenden, das ohne Vorzeichen sein muss. Es ist nicht vorstellbar, diese Wiederholung zu vermeiden. Sie können die Implementierung eines Protokolls, das Bytewerte liest und schreibt, nicht mit nur einem einzigen Verweis auf eine Bytevariable schreiben. Ihre vereinfachte Sichtweise könnte erklären, warum sie sich nie darum gekümmert haben, das Problem zu beheben.In Java gibt es kein vorzeichenloses Byte. Wenn Sie jedoch ein Byte anzeigen möchten, können Sie Folgendes tun:
Ausgabe:
Weitere Informationen finden Sie unter Anzeigen eines Hex / Byte-Werts in Java .
quelle
java.lang.Byte.toUnsignedInt(byte value);
existiert dafür.Gemäß den Einschränkungen in Java ist ein vorzeichenloses Byte im aktuellen Datentypformat fast unmöglich. Sie können für das, was Sie implementieren, nach anderen Bibliotheken einer anderen Sprache suchen und diese dann mit JNI aufrufen .
quelle
Ja und nein. Ich habe mit diesem Problem herumgegraben. Wie ich das verstehe:
Tatsache ist, dass Java Interger -128 bis 127 signiert hat. Es ist möglich, ein in Java nicht signiertes zu präsentieren mit:
Wenn Sie zum Beispiel -12 signierte Nummer hinzufügen, um nicht signiert zu sein, erhalten Sie 244. Sie können diese Nummer jedoch erneut in signiert verwenden. Sie muss wieder auf signiert verschoben werden und wird erneut -12 sein.
Wenn Sie versuchen, dem Java-Byte 244 hinzuzufügen, erhalten Sie outOfIndexException.
Prost..
quelle
java.lang.Byte.toUnsignedInt(byte value);
existiert dafür.Wenn Sie vorzeichenlose Bytes in Java möchten, subtrahieren Sie einfach 256 von der Zahl, an der Sie interessiert sind. Es wird ein Zweierkomplement mit einem negativen Wert erzeugt, der die gewünschte Zahl in vorzeichenlosen Bytes ist.
Beispiel:
Sie müssen solche schmutzigen Hacks verwenden, wenn Sie leJOS verwenden , um den NXT- Baustein zu programmieren .
quelle
speed_unsigned
ist signiert. Drucken Sie es aus und sehen Sie. (Und das- 256
erreicht hier nichts.)