web-dev-qa-db-fra.com

Comment convertir Int en octet non signé et en retour

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?

83
darksky

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
183
JB Nizet

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.

48
Jeffrey Bosboom

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.

7
dm78

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.

3
Péter Török

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.)

2
Gregor

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
1
pgrandjean

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 bytes 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.

1
Ramesh-X

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