J'ai besoin de convertir un nombre en octet non signé. Le nombre est toujours inférieur ou égal à 255, il tiendra donc dans un octet.
J'ai également besoin de reconvertir cet octet en ce nombre. Comment ferais-je cela en Java? J'ai essayé plusieurs façons et aucune ne fonctionne. Voici ce que j'essaye de faire maintenant:
int size = 5;
// Convert size int to binary
String sizeStr = Integer.toString(size);
byte binaryByte = Byte.valueOf(sizeStr);
et maintenant pour reconvertir cet octet en nombre:
Byte test = new Byte(binaryByte);
int msgSize = test.intValue();
De toute évidence, cela ne fonctionne pas. Pour une raison quelconque, il convertit toujours le nombre en 65
. Aucune suggestion?
Réponses:
Un octet est toujours signé en Java. Vous pouvez cependant obtenir sa valeur non signée en la complétant binaire avec 0xFF:
la source
0xFF
aboutissent-ils à un entier non signé? Une explication serait vraiment utile.Java 8 permet
Byte.toUnsignedInt
de convertirbyte
enint
par conversion non signée. Dans le JDK d'Oracle, cela est simplement implémentéreturn ((int) x) & 0xff;
car HotSpot comprend déjà comment optimiser ce modèle, mais il pourrait être intrinsèque sur d'autres VM. Plus important encore, aucune connaissance préalable n'est nécessaire pour comprendre ce qu'un appel àtoUnsignedInt(foo)
faire.Au total, Java 8 fournit des méthodes pour convertir
byte
etshort
en non signéint
etlong
, etint
en non signélong
. Une méthode de conversionbyte
en non signé ashort
été délibérément omise car la JVM ne fournit que l'arithmétique surint
et delong
toute façon.Pour convertir un retour int à un octet, il suffit d' utiliser un casting:
(byte)someInt
. La conversion primitive de rétrécissement résultante supprimera tous les bits sauf les 8 derniers.la source
Si vous avez juste besoin de convertir une valeur 8 bits attendue d'un entier signé en une valeur non signée, vous pouvez utiliser un simple décalage de bits:
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/op3.html
Si vous utilisez autre chose que
int
le type de base, vous devrez évidemment ajuster le montant du décalage: http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.htmlDe plus, gardez à l'esprit que vous ne pouvez pas utiliser de
byte
type, cela entraînera une valeur signée comme mentionné par d'autres répondants. Le plus petit type de primitif que vous pourriez utiliser pour représenter une valeur non signée 8 bits serait ashort
.la source
L'
Integer.toString(size)
appel se convertit en la représentation char de votre entier, c'est-à-dire le char'5'
. La représentation ASCII de ce caractère est la valeur 65.Vous devez d'abord analyser la chaîne en une valeur entière, par exemple en utilisant
Integer.parseInt
, pour récupérer la valeur int originale.En fin de compte, pour une conversion signée / non signée, il est préférable de ne
String
pas figurer dans l'image et d'utiliser la manipulation de bits comme le suggère @JB.la source
String sizeStr = Integer.toString(size); int sizeInt = Integer.parseInt(sizeStr); byte binaryByte = Byte.valueOf((byte) sizeInt);
String.getBytes()
donne les valeurs ASCII des caractères contenus dans le texte, pas les valeurs numériques des chiffres. Vous devez analyser la chaîne en une valeur numérique, comme je l'ai indiqué ci-dessus.La solution fonctionne bien (merci!), Mais si vous voulez éviter le cast et laisser le travail de bas niveau au JDK, vous pouvez utiliser un DataOutputStream pour écrire vos int et un DataInputStream pour les relire. Ils sont automatiquement traités comme non signés octets alors:
Pour convertir des entiers en octets binaires;
Les relire dans:
Esp. utile pour gérer les formats de données binaires (par exemple, les formats de messages plats, etc.)
la source
Sauf que
char
tous les autres types de données numériques en Java sont signés.Comme indiqué dans une réponse précédente, vous pouvez obtenir la valeur non signée en effectuant une
and
opération avec0xFF
. Dans cette réponse, je vais vous expliquer comment cela se passe.Si votre machine est 32 bits, le
int
type de données a besoin de 32 bits pour stocker les valeurs.byte
n'a besoin que de 8 bits.La
int
variablei
est représentée dans la mémoire comme suit (sous la forme d'un entier 32 bits).Ensuite, la
byte
variableb
est représentée par:Comme
byte
s ne sont pas signés, cette valeur représente-22
. (Recherchez le complément de 2 pour en savoir plus sur la façon de représenter des entiers négatifs en mémoire)Ensuite, si vous lancez,
int
c'est toujours-22
parce que le lancer préserve le signe d'un nombre.La
32-bit
valeur castée de l'b
exécution de l'and
opération avec0xFF
.Ensuite, vous obtenez
234
la réponse.la source
Gestion des octets et des entiers non signés avec BigInteger:
la source
Même s'il est trop tard, j'aimerais donner mon avis à ce sujet car cela pourrait clarifier pourquoi la solution proposée par JB Nizet fonctionne. Je suis tombé sur ce petit problème en travaillant sur un analyseur d'octets et à la conversion de chaînes moi-même. Lorsque vous copiez d'un type intégral de taille plus grande vers un type intégral de taille plus petite, comme ce document java dit que cela se produit:
https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.3 Une conversion restrictive d'un entier signé en un type intégral T rejette simplement tout sauf le n le plus bas bits d'ordre, où n est le nombre de bits utilisés pour représenter le type T.En plus d'une éventuelle perte d'informations sur l'amplitude de la valeur numérique, cela peut faire en sorte que le signe de la valeur résultante diffère du signe de la valeur d'entrée .
Vous pouvez être sûr qu'un octet est un type intégral comme ce document java dit https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html octet: Le type de données octet est un deux signés 8 bits complément entier.
Donc, dans le cas de la conversion d'un entier (32 bits) en un octet (8 bits), vous copiez simplement le dernier (8 bits les moins significatifs) de cet entier dans la variable d'octet donnée.
La deuxième partie de l'histoire concerne la manière dont les opérateurs unaires et binaires Java promeuvent les opérandes. https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.6.2 L' élargissement de la conversion primitive (§5.1.2) est appliqué pour convertir l'un ou les deux opérandes comme spécifié par les règles suivantes:
Si l'un des opérandes est de type double, l'autre est converti en double.
Sinon, si l'un des opérandes est de type float, l'autre est converti en float.
Sinon, si l'un des opérandes est de type long, l'autre est converti en long.
Sinon, les deux opérandes sont convertis en type int.
Rassurez-vous, si vous travaillez avec le type intégral int et / ou inférieur, il sera promu en int.
Je me suis aussi gratté la tête :). Il y a une bonne réponse ici par rgettman. Opérateurs binaires en java uniquement pour les entiers et les longs?
la source
Si vous souhaitez utiliser les classes wrapper primitives, cela fonctionnera, mais tous les types java sont signés par défaut.
la source
en java 7
Résultat: 254
la source