¿Cómo convertir una matriz de bytes a su valor numérico (Java)?

89

Tengo una matriz de 8 bytes y quiero convertirla a su valor numérico correspondiente.

p.ej

byte[] by = new byte[8];  // the byte array is stored in 'by'

// CONVERSION OPERATION
// return the numeric value

Quiero un método que realice la operación de conversión anterior.

pirata
fuente
4
¿Qué quiere decir con "valor numérico"? ¿Los bytes representan un número entero (largo) o de punto flotante (doble) en binario? ¿Son la representación en cadena de un número? ¿O otra representación más?
starblue
1
Esto fue útil: stackoverflow.com/questions/5399798/…
TacB0sS
NB: El enlace de TacB0sS era lo que realmente estaba buscando, tanto la conversión hacia adelante como hacia atrás.
Jay Taylor
new BigInteger(by).longValue()
Marqués de Lorne

Respuestas:

106

Suponiendo que el primer byte es el byte menos significativo:

long value = 0;
for (int i = 0; i < by.length; i++)
{
   value += ((long) by[i] & 0xffL) << (8 * i);
}

Si el primer byte es el más significativo, luego es un poco diferente:

long value = 0;
for (int i = 0; i < by.length; i++)
{
   value = (value << 8) + (by[i] & 0xff);
}

Reemplace long con BigInteger , si tiene más de 8 bytes.

Gracias a Aaron Digulla por la corrección de mis errores.

Mnementh
fuente
8
-1 bytes son valores con signo! ¡Y reemplace pow () con shift (<<)! "valor = (valor << 8) + (por [i] y 0xff)"
Aaron Digulla
¿El operador de cambio (<<) tiene prioridad de derecha a izquierda? ¿Cómo funciona el código anterior? Está funcionando todo bien para mí. Solo quiero saber el funcionamiento. Gracias de antemano
suraj
@Mnementh: ¿El operador de desplazamiento (<<) tiene prioridad de derecha a izquierda? ¿Cómo funciona el código anterior? Está funcionando todo bien para mí. Solo quiero saber el funcionamiento. Gracias de antemano
suraj
5
En caso de que alguien más tenga el mismo problema que yo, en el primer ejemplo, por [i] debe convertirse en un largo, de lo contrario, solo funciona para valores inferiores a 2 ^ 32. Es decir,value += ((long)by[i] & 0xffL) << (8 * i);
Lucas
115

Se pueden utilizar los Buffermensajes de correo electrónico que se proporcionan como parte del java.niopaquete para realizar la conversión.

Aquí, la byte[]matriz de origen tiene una longitud de 8, que es el tamaño que se corresponde con un longvalor.

Primero, la byte[]matriz se envuelve en a ByteBuffer, y luego ByteBuffer.getLongse llama al método para obtener el longvalor:

ByteBuffer bb = ByteBuffer.wrap(new byte[] {0, 0, 0, 0, 0, 0, 0, 4});
long l = bb.getLong();

System.out.println(l);

Resultado

4

Me gustaría agradecer a dfa por señalar el ByteBuffer.getLongmétodo en los comentarios.


Aunque puede que no sea aplicable en esta situación, la belleza de Buffers viene con mirar una matriz con múltiples valores.

Por ejemplo, si tuviéramos una matriz de 8 bytes y quisiéramos verla como dos intvalores, podríamos envolver la byte[]matriz en an ByteBuffer, que se ve como a IntBuffery obtener los valores mediante IntBuffer.get:

ByteBuffer bb = ByteBuffer.wrap(new byte[] {0, 0, 0, 1, 0, 0, 0, 4});
IntBuffer ib = bb.asIntBuffer();
int i0 = ib.get(0);
int i1 = ib.get(1);

System.out.println(i0);
System.out.println(i1);

Resultado:

1
4
coobird
fuente
¿qué pasa con ByteBuffer.wrap (nuevo byte [] {0, 0, 0, 1, 0, 0, 0, 4}). getLong ()? este método debe leer los siguientes 8 bytes y convertirlos en long
dfa
@dfa: Gracias por señalar eso, seguro que parece funcionar. Editaré la respuesta. :)
coobird
16

Si se trata de un valor numérico de 8 bytes, puede intentar:

BigInteger n = new BigInteger(byteArray);

Si se trata de un búfer de caracteres UTF-8, puede intentar:

BigInteger n = new BigInteger(new String(byteArray, "UTF-8"));
Vincent Robert
fuente
Habría votado por esta respuesta si terminara justo después del primer fragmento de código, o si incluyera algún código para convertir la cadena en un "valor numérico". Tal como está, la segunda mitad de su respuesta parece una incongruencia.
Laurence Gonsalves
No es lo que quise decir en primer lugar, cambié mi respuesta
Vincent Robert
15

Simplemente, puede usar o consultar guava lib proporcionada por Google, que ofrece métodos útiles para la conversión entre matriz larga y de bytes. Mi código de cliente:

    long content = 212000607777l;
    byte[] numberByte = Longs.toByteArray(content);
    logger.info(Longs.fromByteArray(numberByte));
Chen Yi
fuente
9

También puede utilizar BigInteger para bytes de longitud variable. Puede convertirlo a largo, entero o corto, lo que se adapte a sus necesidades.

new BigInteger(bytes).intValue();

o para denotar polaridad:

new BigInteger(1, bytes).intValue();
Jamel Toms
fuente
1

Cada celda de la matriz se trata como unsigned int:

private int unsignedIntFromByteArray(byte[] bytes) {
int res = 0;
if (bytes == null)
    return res;


for (int i=0;i<bytes.length;i++){
    res = res | ((bytes[i] & 0xff) << i*8);
}
return res;
}
Asaf Pinhassi
fuente
Solo una nota de que necesitaba usar 0xFFL, de lo contrario, la conversión de int 0xFF a long tenía una gran cantidad de 1 bits incorrectos configurados cuando imprimí Long.toHexString (l).
Luke
Debe usar 0xFFL; de lo contrario, obtendrá la extensión de signo.
Gray