Conversión Byte Array e Int en Java

Tengo algunas dificultades con estas dos funciones: byteArrayToInt e intToByteArray .

El problema es que si uso uno para llegar a otro y ese resultado para llegar al primero, los resultados son diferentes, como puede ver en mis ejemplos a continuación.

No puedo encontrar el error en el código. Cualquier idea es bienvenida. Gracias.

 public static void main(String[] args) { int a = 123; byte[] aBytes = intToByteArray(a); int a2 = byteArrayToInt(aBytes); System.out.println(a); // prints '123' System.out.println(aBytes); // prints '[B@459189e1' System.out.println(a2); // prints '2063597568 System.out.println(intToByteArray(a2)); // prints '[B@459189e1' } public static int byteArrayToInt(byte[] b) { int value = 0; for (int i = 0; i < 4; i++) { int shift = (4 - 1 - i) * 8; value += (b[i] & 0x000000FF) <> 8) & 0xFF); ret[2] = (byte) ((a >> 16) & 0xFF); ret[3] = (byte) ((a >> 24) & 0xFF); return ret; } 

Estás intercambiando endianidad entre tus dos métodos. Tiene intToByteArray(int a) asignando los bits de orden inferior a ret[0] , pero luego byteArrayToInt(byte[] b) asigna b[0] a los bits de orden superior del resultado. Necesitas invertir uno u otro, como:

 public static byte[] intToByteArray(int a) { byte[] ret = new byte[4]; ret[3] = (byte) (a & 0xFF); ret[2] = (byte) ((a >> 8) & 0xFF); ret[1] = (byte) ((a >> 16) & 0xFF); ret[0] = (byte) ((a >> 24) & 0xFF); return ret; } 

Tus métodos deberían ser (algo así como)

 public static int byteArrayToInt(byte[] b) { return b[3] & 0xFF | (b[2] & 0xFF) << 8 | (b[1] & 0xFF) << 16 | (b[0] & 0xFF) << 24; } public static byte[] intToByteArray(int a) { return new byte[] { (byte) ((a >> 24) & 0xFF), (byte) ((a >> 16) & 0xFF), (byte) ((a >> 8) & 0xFF), (byte) (a & 0xFF) }; } 

Estos métodos fueron probados con el siguiente código:

 Random rand = new Random(System.currentTimeMillis()); byte[] b; int a, v; for (int i=0; i<10000000; i++) { a = rand.nextInt(); b = intToByteArray(a); v = byteArrayToInt(b); if (a != v) { System.out.println("ERR! " + a + " != " + Arrays.toString(b) + " != " + v); } } System.out.println("Done!"); 

Eso es mucho trabajo para:

 public static int byteArrayToLeInt(byte[] b) { final ByteBuffer bb = ByteBuffer.wrap(b); bb.order(ByteOrder.LITTLE_ENDIAN); return bb.getInt(); } public static byte[] leIntToByteArray(int i) { final ByteBuffer bb = ByteBuffer.allocate(Integer.SIZE / Byte.SIZE); bb.order(ByteOrder.LITTLE_ENDIAN); bb.putInt(i); return bb.array(); } 

Este método usa la funcionalidad Java ByteBuffer y ByteOrder en el paquete java.nio . Este código debe preferirse cuando se requiere legibilidad. También debería ser muy fácil de recordar.

He mostrado el orden de bytes Little Endian aquí. Para crear una versión de Big Endian, simplemente puede omitir la llamada al order(ByteOrder) .


En el código donde el rendimiento es de mayor prioridad que la legibilidad (aproximadamente 10 veces más rápido):

 public static int byteArrayToLeInt(byte[] encodedValue) { int value = (encodedValue[3] << (Byte.SIZE * 3)); value |= (encodedValue[2] & 0xFF) << (Byte.SIZE * 2); value |= (encodedValue[1] & 0xFF) << (Byte.SIZE * 1); value |= (encodedValue[0] & 0xFF); return value; } public static byte[] leIntToByteArray(int value) { byte[] encodedValue = new byte[Integer.SIZE / Byte.SIZE]; encodedValue[3] = (byte) (value >> Byte.SIZE * 3); encodedValue[2] = (byte) (value >> Byte.SIZE * 2); encodedValue[1] = (byte) (value >> Byte.SIZE); encodedValue[0] = (byte) value; return encodedValue; } 

Simplemente invierta el índice de matriz de bytes para contar de cero a tres para crear una versión Big Endian de este código.


Notas:

  • En Java 8 también puede hacer uso de la constante Integer.BYTES , que es más sucinta que Integer.SIZE / Byte.SIZE .

También puede usar BigInteger para bytes de longitud variable. Puede convertirlo en Largo, Entero o Corto, según sus necesidades.

 new BigInteger(bytes).intValue(); 

o para denotar la polaridad:

 new BigInteger(1, bytes).intValue(); 

Para recuperar los bytes solo:

 new BigInteger(bytes).toByteArray() 

Me gusta la respuesta original de owlstead, y si no te gusta la idea de crear un ByteBuffer en cada llamada a un método, puedes reutilizar el ByteBuffer llamando a los .clear() y .flip() :

 ByteBuffer _intShifter = ByteBuffer.allocate(Integer.SIZE / Byte.SIZE) .order(ByteOrder.LITTLE_ENDIAN); public byte[] intToByte(int value) { _intShifter.clear(); _intShifter.putInt(value); return _intShifter.array(); } public int byteToInt(byte[] data) { _intShifter.clear(); _intShifter.put(data, 0, Integer.SIZE / Byte.SIZE); _intShifter.flip(); return _intShifter.getInt(); } 

Encontré una manera simple en com.google.common.primitives que está en [Maven: com.google.guava: guava: 12.0.1]

 long newLong = Longs.fromByteArray(oldLongByteArray); int newInt = Ints.fromByteArray(oldIntByteArray); 

Que tengas un buen bash 🙂

Eché un vistazo a muchas preguntas como esta y encontré esta publicación … No me gustó el hecho de que el código de conversión esté duplicado para cada tipo, así que hice un método genérico para realizar la tarea:

 public static byte[] toByteArray(long value, int n) { byte[] ret = new byte[n]; ret[n-1] = (byte) ((value >> (0*8) & 0xFF); ret[n-2] = (byte) ((value >> (1*8) & 0xFF); ... ret[1] = (byte) ((value >> ((n-2)*8) & 0xFF); ret[0] = (byte) ((value >> ((n-1)*8) & 0xFF); return ret; } 

Ver la publicación completa .

/ * lo siento, este es el correcto * /

  public byte[] IntArrayToByteArray(int[] iarray , int sizeofintarray) { final ByteBuffer bb ; bb = ByteBuffer.allocate( sizeofintarray * 4); for(int k = 0; k < sizeofintarray ; k++) bb.putInt(k * 4, iar[k]); return bb.array(); } 

En lugar de asignar espacio, et al, un enfoque que utiliza ByteBuffer de java.nio ….

 byte[] arr = { 0x01, 0x00, 0x00, 0x00, 0x48, 0x01}; // say we want to consider indices 1, 2, 3, 4 {0x00, 0x00, 0x00, 0x48}; ByteBuffer bf = ByteBuffer.wrap(arr, 1, 4); // big endian by default int num = bf.getInt(); // 72 

Ahora, para ir por el otro lado.

 ByteBuffer newBuf = ByteBuffer.allocate(4); newBuf.putInt(num); byte[] bytes = newBuf.array(); // [0, 0, 0, 72] {0x48 = 72} 

aquí está mi implementación

 public static byte[] intToByteArray(int a) { return BigInteger.valueOf(a).toByteArray(); } public static int byteArrayToInt(byte[] b) { return new BigInteger(b).intValue(); }