Eu quero armazenar alguns dados em matrizes de bytes em Java. Basicamente, apenas números que podem levar até 2 bytes por número.
Gostaria de saber como converter um número inteiro em uma matriz de 2 bytes e vice-versa. Encontrei muitas soluções pesquisando no Google, mas a maioria delas não explica o que acontece no código. Há muitas coisas que eu realmente não entendo, então eu apreciaria uma explicação básica.
java
types
endianness
Chris
fonte
fonte
Respostas:
Use as classes encontradas no
java.nio
espaço para nome, em particular oByteBuffer
. Pode fazer todo o trabalho para você.fonte
ByteBuffer
.wrap
eallocate
, eles não retornam uma instância da classe abstrataByteBuffer
.Char
,Short
,Int
. Suponho que eu poderia preencher até 4 bytes e descartar o quarto de cada vez, mas prefiro não.Ao compactar bytes assinados em um int, cada byte precisa ser mascarado porque é estendido para 32 bits (em vez de estendido para zero) devido à regra aritmética de promoção (descrita em JLS, Conversões e Promoções).
Há um quebra-cabeça interessante relacionado a isso descrito em Java Puzzlers ("Um grande prazer em todos os bytes") de Joshua Bloch e Neal Gafter. Ao comparar um valor de byte com um valor int, o byte é estendido para um int e, em seguida, esse valor é comparado ao outro int
Observe que todos os tipos numéricos são assinados em Java, com exceção do char sendo um tipo inteiro não assinado de 16 bits.
fonte
& 0xFF
são desnecessários.& 0xFF
são necessários, pois informa a JVM para converter o byte assinado em um número inteiro com apenas esses bits definidos. Caso contrário, o byte -1 (0xFF) se transformará no int -1 (0xFFFFFFFF). Eu posso estar errado e, mesmo estando, não dói e torna as coisas mais claras.byte b = 0; b |= 0x88; System.out.println(Integer.toString(b, 16)); //Output: -78 System.out.println(Integer.toString(b & 0xFF, 16)); //Output: 88
byte
com 0xFF (int
), a JVM converterá obyte
paraint
com 1 estendido ou 0 estendido de acordo com o bit inicial primeiro. Não há byte não assinado em Java,byte
sempre são assinados.ByteBuffer.getInt()
:Reads the next four bytes at this buffer's current position
apenas os primeiros 4 bytes será analisado, que não deve ser o que quiser.Você também pode usar o BigInteger para bytes de comprimento variável. Você pode convertê-lo para comprido, int ou curto, conforme a sua necessidade.
ou para denotar polaridade:
Para recuperar bytes apenas:
fonte
intValueExact
, nãointValue
Uma implementação básica seria algo como isto:
Para entender as coisas, você pode ler este artigo do WP: http://en.wikipedia.org/wiki/Endianness
O código fonte acima será exibido
34 12 78 56 bc 9a
. Os primeiros 2 bytes (34 12
) representam o primeiro número inteiro etc. O código fonte acima codifica números inteiros no formato little endian.fonte
fonte
Alguém com um requisito onde eles precisam ler de bits, digamos que você precise ler apenas de 3 bits, mas você precisa de um número inteiro assinado e use o seguinte:
O número mágico
3
pode ser substituído pelo número de bits (não bytes) que você está usando.fonte
Com freqüência, goiaba tem o que você precisa.
Para passar da matriz de bytes para int
Ints.fromBytesArray
:, doc aquiPara ir da matriz de int para byte:,
Ints.toByteArray
doc aquifonte
Eu acho que este é o melhor modo de transmitir para int
primeiro byte de conversão para String
próximo passo é converter para um int
mas byte está na faixa de -128 a 127 para este reasone, acho melhor usar a faixa de 0 a 255 e você só precisa fazer isso:
fonte