Como converter uma matriz de bytes em seu valor numérico (Java)?

89

Eu tenho uma matriz de 8 bytes e quero convertê-la em seu valor numérico correspondente.

por exemplo

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

// CONVERSION OPERATION
// return the numeric value

Quero um método que execute a operação de conversão acima.

pirata
fonte
4
O que você quer dizer com "valor numérico"? Os bytes representam um número inteiro (longo) ou um número de ponto flutuante (duplo) em binário? Eles são a representação em cadeia de um número? Ou ainda outra representação?
starblue
1
Isso foi útil: stackoverflow.com/questions/5399798/…
TacB0sS
NB: O link do TacB0sS era o que eu estava realmente procurando - conversão para frente e para trás.
Jay Taylor
new BigInteger(by).longValue()
Marquês de Lorne

Respostas:

106

Supondo que o primeiro byte seja o byte menos significativo:

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

É o primeiro byte o mais significativo, então é um pouco diferente:

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

Substitua long por BigInteger , se você tiver mais de 8 bytes.

Agradeço a Aaron Digulla pela correção de meus erros.

Mnementh
fonte
8
-1 bytes são valores com sinal! E substitua pow () por shift (<<)! "valor = (valor << 8) + (por [i] e 0xff)"
Aaron Digulla
O operador de deslocamento (<<) tem precedência da direita para a esquerda? Como funciona o código acima? Está funcionando bem para mim. Só quero saber como funciona. Agradecimento antecipado
suraj
@Mnementh: O operador de deslocamento (<<) tem precedência da direita para a esquerda? Como funciona o código acima? Está funcionando bem para mim. Só quero saber como funciona. Agradecimento antecipado
suraj
5
No caso de outra pessoa ter o mesmo problema que eu, no primeiro exemplo, por [i] deve ser convertido para um longo, caso contrário, só funciona para valores menores que 2 ^ 32. Ou seja,value += ((long)by[i] & 0xffL) << (8 * i);
Lucas,
115

Pode-se usar os programas Bufferfornecidos como parte do java.niopacote para realizar a conversão.

Aqui, a byte[]matriz de origem tem um comprimento de 8, que é o tamanho que corresponde a um longvalor.

Primeiro, a byte[]matriz é envolvida em um ByteBuffere, em seguida, o ByteBuffer.getLongmétodo é chamado para obter o 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

Gostaria de agradecer ao dfa por apontar o ByteBuffer.getLongmétodo nos comentários.


Embora possa não ser aplicável nesta situação, a beleza do Buffers vem com a observação de uma matriz com vários valores.

Por exemplo, se tivéssemos uma matriz de 8 bytes e quiséssemos vê-la como dois intvalores, poderíamos envolver a byte[]matriz em um ByteBuffer, que é visto como a, IntBuffere obter os valores por 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
fonte
que tal ByteBuffer.wrap (new byte [] {0, 0, 0, 1, 0, 0, 0, 4}). getLong ()? este método deve ler próxima de 8 bytes e convertê-los para um longo
dfa
@dfa: Obrigado por apontar isso, com certeza parece funcionar - vou editar a resposta. :)
coobird
16

Se este for um valor numérico de 8 bytes, você pode tentar:

BigInteger n = new BigInteger(byteArray);

Se este for um buffer de caracteres UTF-8, você pode tentar:

BigInteger n = new BigInteger(new String(byteArray, "UTF-8"));
Vincent Robert
fonte
Eu teria votado nesta resposta se terminasse logo após o primeiro trecho de código, ou se incluísse algum código para converter a string em um "valor numérico". Como está, a segunda metade de sua resposta parece um non sequitur.
Laurence Gonsalves
Não o que eu quis dizer em primeiro lugar, eu mudei minha resposta
Vincent Robert
15

Simplesmente, você pode usar ou referir-se à lib guava fornecida pelo google, que oferece métodos úteis para conversão entre array longo e byte. Meu código de cliente:

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

Você também pode usar BigInteger para bytes de comprimento variável. Você pode convertê-lo em Long, Integer ou Short, o que for mais adequado às suas necessidades.

new BigInteger(bytes).intValue();

ou para denotar polaridade:

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

Cada célula na matriz é tratada como int sem sinal:

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
fonte
Apenas uma observação de que eu precisava usar 0xFFL, caso contrário, a conversão de int 0xFF para long tinha um monte de 1 bits incorretos definidos quando imprimi Long.toHexString (l).
Lucas
Você precisa usar 0xFFL, caso contrário, obterá extensão de sinal.
cinza