it-swarm.it

Come convertire Int in byte senza segno e viceversa

Devo convertire un numero in un byte senza segno. Il numero è sempre inferiore o uguale a 255, quindi si adatta a un byte.

Ho anche bisogno di riconvertire quel byte in quel numero. Come lo farei in Java? Ho provato diversi modi e nessuno funziona. Ecco cosa sto cercando di fare ora:

int size = 5;
// Convert size int to binary
String sizeStr = Integer.toString(size);
byte binaryByte = Byte.valueOf(sizeStr);

e ora per riconvertire quel byte nel numero:

Byte test = new Byte(binaryByte);
int msgSize = test.intValue();

Chiaramente, questo non funziona. Per qualche motivo, converte sempre il numero in 65. Eventuali suggerimenti?

83
darksky

Un byte è sempre firmato in Java. Puoi ottenere il suo valore senza segno binario e inserendolo con 0xFF, tuttavia:

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 fornisce Byte.toUnsignedInt per convertire byte in int mediante conversione senza segno. In Oracle JDK questo è semplicemente implementato come return ((int) x) & 0xff; perché HotSpot capisce già come ottimizzare questo modello, ma potrebbe essere intrinseco su altre VM. Ancora più importante, non è necessaria alcuna conoscenza preliminare per capire cosa fa una chiamata a toUnsignedInt(foo).

In totale, Java 8 fornisce metodi per convertire byte e short in unsigned int e long e int in unsigned long. Un metodo per convertire byte in unsigned short era omesso deliberatamente perché la JVM fornisce aritmetica solo su int e long comunque.

Per convertire un int di nuovo in un byte, basta usare un cast: (byte)someInt. Il risultante restringimento della conversione primitiva eliminerà tutti tranne gli ultimi 8 bit.

48
Jeffrey Bosboom

Se hai solo bisogno di convertire un valore atteso di 8 bit da un int firmato in un valore non firmato, puoi usare il semplice spostamento dei bit:

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

Se usi qualcosa di diverso da int come tipo di base, dovrai ovviamente regolare l'importo del turno: http://docs.Oracle.com/javase/tutorial/Java/nutsandbolts/datatypes .html

Inoltre, tieni presente che non puoi utilizzare il tipo byte, poiché ciò comporterà un valore con segno, come indicato da altri risponditori. Il tipo primitivo più piccolo che potresti usare per rappresentare un valore senza segno a 8 bit sarebbe un short.

7
dm78

La chiamata Integer.toString(size) viene convertita nella rappresentazione char del tuo numero intero, ovvero char '5'. rappresentazione ASCII di quel carattere è il valore 65.

Devi prima analizzare la stringa in un valore intero, ad es. usando Integer.parseInt , per ripristinare il valore int originale.

Come linea di fondo, per una conversione firmata/non firmata, è meglio lasciare String fuori dall'immagine e usare la manipolazione dei bit come suggerisce @JB.

3
Péter Török

La soluzione funziona bene (grazie!), Ma se vuoi evitare il casting e lasciare il lavoro di basso livello su JDK, puoi utilizzare un DataOutputStream per scrivere i tuoi int e un DataInputStream per rileggerli. Vengono automaticamente trattati come non firmati byte quindi:

Per convertire int's in byte binari;

ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
int val = 250;
dos.write(byteVal);
...
dos.flush();

Rileggendoli in:

// 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 per gestire formati di dati binari (ad es. formati di messaggi flat, ecc.)

2
Gregor

Gestione di byte e numeri interi senza segno con 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

Tranne char, tutti gli altri tipi di dati numerici in Java sono firmati.

Come detto in una risposta precedente, puoi ottenere il valore senza segno eseguendo un'operazione and con 0xFF. In questa risposta, spiegherò come succede.

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

Se la macchina è a 32 bit, il tipo di dati int richiede 32 bit per memorizzare i valori. byte richiede solo 8 bit.

La variabile inti è rappresentata nella memoria come segue (come numero intero a 32 bit).

0{24}11101010

Quindi la variabile byteb è rappresentata come:

11101010

Poiché bytes non sono firmati, questo valore rappresenta -22. (Cerca il complemento di 2 per saperne di più su come rappresentare numeri interi negativi in ​​memoria)

Quindi se esegui il cast è int sarà comunque -22 perché il casting conserva il segno di un numero.

1{24}11101010

The the casted 32-bit valore di b esegue l'operazione and con 0xFF.

 1{24}11101010 & 0{24}11111111
=0{24}11101010

Quindi ottieni 234 come risposta.

1
Ramesh-X

Se si desidera utilizzare le classi wrapper primitive, funzionerà, ma tutti i tipi Java sono firmati per impostazione predefinita.

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