Convertir entero en matriz de bytes (Java)

137

¿Cuál es una forma rápida de convertir un Integeren un Byte Array?

p.ej 0xAABBCCDD => {AA, BB, CC, DD}

Botón de oro
fuente
1
¿Importa qué formato tiene la matriz de bytes resultante? Que harás con eso?
skaffman

Respuestas:

237

Echa un vistazo a la clase ByteBuffer .

ByteBuffer b = ByteBuffer.allocate(4);
//b.order(ByteOrder.BIG_ENDIAN); // optional, the initial order of a byte buffer is always BIG_ENDIAN.
b.putInt(0xAABBCCDD);

byte[] result = b.array();

Configuración garantiza el orden de bytes que result[0] == 0xAA, result[1] == 0xBB, result[2] == 0xCCy result[3] == 0xDD.

O, alternativamente, puede hacerlo manualmente:

byte[] toBytes(int i)
{
  byte[] result = new byte[4];

  result[0] = (byte) (i >> 24);
  result[1] = (byte) (i >> 16);
  result[2] = (byte) (i >> 8);
  result[3] = (byte) (i /*>> 0*/);

  return result;
}

Sin ByteBufferembargo, la clase fue diseñada para tareas tan sucias. De hecho, lo privado java.nio.Bitsdefine estos métodos auxiliares que son utilizados por ByteBuffer.putInt():

private static byte int3(int x) { return (byte)(x >> 24); }
private static byte int2(int x) { return (byte)(x >> 16); }
private static byte int1(int x) { return (byte)(x >>  8); }
private static byte int0(int x) { return (byte)(x >>  0); }
Gregory Pakosz
fuente
3
esto funcionaría bien si el bytebuffer ya está allí ... de lo contrario, parece que tomaría más tiempo hacer la asignación, que solo asignar una matriz de bytes de longitud 4 y hacer el cambio manualmente ... pero probablemente estamos hablando sobre pequeñas diferencias
Jason S
La instancia de ByteBuffer se puede almacenar en caché; e internamente seguramente se implementa con desplazamiento y enmascaramiento de todos modos.
Gregory Pakosz
44
Esta es una respuesta perfectamente buena. Tenga en cuenta que big-endian es el valor predeterminado especificado, y los métodos son "encadenables", y el argumento de posición es opcional, por lo que todo se reduce a: byte [] result = ByteBuffer.allocate (4) .putInt (0xAABBCCDD) .array ( ); Por supuesto, si está haciendo esto repetidamente y concatenando todos los resultados juntos (lo cual es común cuando está haciendo este tipo de cosas), asigne un único búfer y ponga repetidamenteFoo () todas las cosas que necesita: hará un seguimiento del desplazamiento a medida que avanza. Realmente es una clase tremendamente útil.
Kevin Bourrillion
¿Qué aporta a los tipos firmados?
Gregory Pakosz
3
Para quien no sabe. PutInt siempre escribirá 4 bytes, sin importar el tamaño del entero de entrada. Si solo quieres 2 bytes, usa putShort, etc ...
bvdb
36

Utilizando BigInteger:

private byte[] bigIntToByteArray( final int i ) {
    BigInteger bigInt = BigInteger.valueOf(i);      
    return bigInt.toByteArray();
}

Utilizando DataOutputStream:

private byte[] intToByteArray ( final int i ) throws IOException {      
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    DataOutputStream dos = new DataOutputStream(bos);
    dos.writeInt(i);
    dos.flush();
    return bos.toByteArray();
}

Utilizando ByteBuffer:

public byte[] intToBytes( final int i ) {
    ByteBuffer bb = ByteBuffer.allocate(4); 
    bb.putInt(i); 
    return bb.array();
}
Pascal Thivent
fuente
55
prestar atención a la orden de bytes, aunque
Gregory Pakosz
1
¿ByteBuffer da un int sin firmar?
Arun George
@Pascal Usando ByteBuffer Intenté con ByteBuffer bb = ByteBuffer.allocate (3); Para esto, está dando java.nio.BufferOverflowException, no entiendo por qué no funciona con un valor inferior a 4. ¿Puede usted explicar por favor?
Sanjay Jain
@SanjayJain Obtiene una excepción de desbordamiento de búfer porque los ints en Java tienen un tamaño de 32 bits o 4 bytes y, por lo tanto, requieren que asigne al menos 4 bytes de memoria en su ByteBuffer.
impactante
@GregoryPakosz tiene razón sobre el orden de bytes. Su respuesta usando ByteBufferes más intuitiva si se trata de un int mayor que 2 ^ 31 - 1.
ordonezalex
31

usa esta función me funciona

public byte[] toByteArray(int value) {
    return new byte[] {
            (byte)(value >> 24),
            (byte)(value >> 16),
            (byte)(value >> 8),
            (byte)value};
}

traduce el int en un valor de byte

daz
fuente
Tampoco vale la pena que esto funcione independientemente del bit más significativo y más eficiente en comparación con las otras respuestas. También podría usar '>>'.
algolicious
1
Una solución directa como esta es ciertamente más rápida que llamar a cualquier método de biblioteca. A veces solo tiene que jugar con los bits directamente con unas pocas líneas de código en lugar de incurrir en todos los gastos adicionales de las llamadas al método de la biblioteca.
David R Tribble
Y esto convierte bien entre idiomas, por lo que es bueno para el desarrollo de software en varios idiomas.
El coordinador el
15

Si te gusta la guayaba , puedes usar su Intsclase:


Para intbyte[], use toByteArray():

byte[] byteArray = Ints.toByteArray(0xAABBCCDD);

El resultado es {0xAA, 0xBB, 0xCC, 0xDD}.


Su reverso es fromByteArray()o fromBytes():

int intValue = Ints.fromByteArray(new byte[]{(byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD});
int intValue = Ints.fromBytes((byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD);

El resultado es 0xAABBCCDD.

Angustia
fuente
8

Puedes usar BigInteger:

De enteros:

byte[] array = BigInteger.valueOf(0xAABBCCDD).toByteArray();
System.out.println(Arrays.toString(array))
// --> {-86, -69, -52, -35 }

La matriz devuelta es del tamaño que se necesita para representar el número, por lo que podría ser del tamaño 1, para representar 1, por ejemplo. Sin embargo, el tamaño no puede ser más de cuatro bytes si se pasa un int.

De cuerdas:

BigInteger v = new BigInteger("AABBCCDD", 16);
byte[] array = v.toByteArray();

Sin embargo, deberá tener cuidado, si el primer byte es mayor 0x7F(como en este caso), donde BigInteger insertaría un byte 0x00 al comienzo de la matriz. Esto es necesario para distinguir entre valores positivos y negativos.

notnoop
fuente
¡Gracias! Pero como se trata de BigInteger, ¿los ints se ajustarán correctamente? ¿Son enteros que están fuera de Integer.MAX_VALUE pero que todavía se pueden representar con solo 4 bytes?
Buttercup
1
Esto ciertamente no es rápido de ejecutar. ;)
Peter Lawrey
Esta no es una buena opción. No solo puede agregar 0x00 bytes, también puede eliminar los ceros iniciales.
ZZ Coder
1

Solución simple que maneja adecuadamente ByteOrder:

ByteBuffer.allocate(4).order(ByteOrder.nativeOrder()).putInt(yourInt).array();

helmy
fuente
1

muy fácil con android

int i=10000;
byte b1=(byte)Color.alpha(i);
byte b2=(byte)Color.red(i);
byte b3=(byte)Color.green(i);
byte b4=(byte)Color.blue(i);
Mukesh Bambhaniya
fuente
1

Esto te ayudara.

import java.nio.ByteBuffer;
import java.util.Arrays;

public class MyClass
{
    public static void main(String args[]) {
        byte [] hbhbytes = ByteBuffer.allocate(4).putInt(16666666).array();

        System.out.println(Arrays.toString(hbhbytes));
    }
}
wai
fuente
0

También puede cambiar

byte[] ba = new byte[4];
int val = Integer.MAX_VALUE;

for(byte i=0;i<4;i++)
    ba[i] = (byte)(val >> i*8);
    //ba[3-i] = (byte)(val >> i*8); //Big-endian
Mate
fuente
0

Aquí hay un método que debería hacer el trabajo correctamente.

public byte[] toByteArray(int value)
{
    final byte[] destination = new byte[Integer.BYTES];
    for(int index = Integer.BYTES - 1; index >= 0; index--)
    {
        destination[i] = (byte) value;
        value = value >> 8;
    };
    return destination;
};
usuario3424779
fuente
0

Es mi solucion:

public void getBytes(int val) {
    byte[] bytes = new byte[Integer.BYTES];
    for (int i = 0;i < bytes.length; i ++) {
        int j = val % Byte.MAX_VALUE;
        bytes[i] = (j == 0 ? Byte.MAX_VALUE : j);
    }
}

También Stringy método:

public void getBytes(int val) {
    String hex = Integer.toHexString(val);
    byte[] val = new byte[hex.length()/2]; // because byte is 2 hex chars
    for (int i = 0; i < hex.length(); i+=2)
        val[i] = Byte.parseByte("0x" + hex.substring(i, i+2), 16);
    return val;
}
Muskovets
fuente