Je dois convertir un nombre en octet non signé. Le nombre est toujours inférieur ou égal à 255 et ne peut donc contenir qu'un octet.
Je dois aussi reconvertir cet octet en ce nombre. Comment ferais-je cela en Java? J'ai essayé plusieurs méthodes et aucune ne fonctionne. Voici ce que j'essaie 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();
Clairement, cela ne fonctionne pas. Pour une raison quelconque, il convertit toujours le nombre en 65
. Aucune suggestion?
Un octet est toujours signé en Java. Vous pouvez obtenir sa valeur non signée en exécutant binaire avec 0xFF, cependant:
int i = 234;
byte b = (byte) i;
System.out.println(b); // -22
int i2 = b & 0xFF;
System.out.println(i2); // 234
Java 8 fournit Byte.toUnsignedInt
pour convertir byte
en int
par conversion non signée. Dans le JDK d’Oracle, il s’agit simplement de return ((int) x) & 0xff;
, car HotSpot sait déjà comment optimiser ce modèle, mais il peut être intrinsèque sur d’autres machines virtuelles. Plus important encore, aucune connaissance préalable n'est nécessaire pour comprendre ce que fait un appel à toUnsignedInt(foo)
.
Au total, Java 8 fournit des méthodes pour convertir byte
et short
en non signé int
et long
et int
à non signé long
. Une méthode pour convertir byte
en non signé short
a été délibérément omise car la machine virtuelle Java ne fournit de toute façon une arithmétique que sur int
et long
.
Pour reconvertir un int en octet, utilisez simplement un transtypage: (byte)someInt
. La conversion primitive restrictive résultante supprimera tous les bits sauf les 8 derniers.
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:
int signed = -119; // 11111111 11111111 11111111 10001001
/**
* Use unsigned right shift operator to drop unset bits in positions 8-31
*/
int psuedoUnsigned = (signed << 24) >>> 24; // 00000000 00000000 00000000 10001001 -> 137 base 10
/**
* Convert back to signed by using the sign-extension properties of the right shift operator
*/
int backToSigned = (psuedoUnsigned << 24) >> 24; // back to original bit pattern
http://docs.Oracle.com/javase/tutorial/Java/nutsandbolts/op3.html
Si vous utilisez autre chose que int
comme type de base, vous devrez évidemment ajuster le montant du décalage: http://docs.Oracle.com/javase/tutorial/Java/nutsandbolts/datatypes .html
De plus, gardez à l'esprit que vous ne pouvez pas utiliser le type byte
, vous obtiendrez une valeur signée comme mentionné par les autres répondants. Le plus petit type de primitive que vous pourriez utiliser pour représenter une valeur non signée sur 8 bits serait un short
.
L’appel Integer.toString(size)
est converti en représentation sous forme de caractère de votre entier, c’est-à-dire le caractère '5'
. Le 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 d'origine.
En bout de ligne, pour une conversion signée/non signée, il est préférable de laisser String
hors de l’image et d’utiliser une manipulation de bits comme le suggère @JB.
La solution fonctionne bien (merci!), Mais si vous souhaitez éviter les transformations et laisser le travail de bas niveau au JDK, vous pouvez utiliser un DataOutputStream pour écrire vos entiers et un DataInputStream pour les relire. Ils sont automatiquement traités comme non signés. octets alors:
Pour convertir les int en octets binaires;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
int val = 250;
dos.write(byteVal);
...
dos.flush();
Les relisant dans:
// important to use a (non-Unicode!) encoding like US_ASCII or ISO-8859-1,
// i.e., one that uses one byte per character
ByteArrayInputStream bis = new ByteArrayInputStream(
bos.toString("ISO-8859-1").getBytes("ISO-8859-1"));
DataInputStream dis = new DataInputStream(bis);
int byteVal = dis.readUnsignedByte();
Esp. utile pour gérer les formats de données binaires (par exemple, les formats de message à plat, etc.)
Gestion des octets et des entiers non signés avec BigInteger:
byte[] b = ... // your integer in big-endian
BigInteger ui = new BigInteger(b) // let BigInteger do the work
int i = ui.intValue() // unsigned value assigned to i
Excepté char
, tous les autres types de données numériques entre Java sont signés.
Comme indiqué dans une réponse précédente, vous pouvez obtenir la valeur non signée en effectuant une opération and
avec 0xFF
. Dans cette réponse, je vais expliquer comment cela se passe.
int i = 234;
byte b = (byte) i;
System.out.println(b); // -22
int i2 = b & 0xFF;
// This is like casting b to int and perform and operation with 0xFF
System.out.println(i2); // 234
Si votre machine est 32 bits, le type de données int
nécessite 32 bits pour stocker les valeurs. byte
n'a besoin que de 8 bits.
La int
variable i
est représentée dans la mémoire comme suit (sous la forme d'un entier de 32 bits).
0{24}11101010
Ensuite, la byte
variable b
est représentée par:
11101010
Comme byte
s ne sont pas signés, cette valeur représente -22
. (Recherchez le complément à 2 pour en savoir plus sur la représentation des nombres entiers négatifs en mémoire)
Ensuite, si vous lancez est int
ce sera toujours -22
parce que la coulée conserve le signe d’un nombre.
1{24}11101010
Les castés 32-bit
valeur de b
exécuter and
opération avec 0xFF
.
1{24}11101010 & 0{24}11111111
=0{24}11101010
Ensuite, vous obtenez 234
comme réponse.
Si vous souhaitez utiliser les classes wrapper primitives, cela fonctionnera, mais tous les types Java) sont signés par défaut.
public static void main(String[] args) {
Integer i=5;
Byte b = Byte.valueOf(i+""); //converts i to String and calls Byte.valueOf()
System.out.println(b);
System.out.println(Integer.valueOf(b));
}