Preciso converter um número em um byte sem sinal. O número é sempre menor ou igual a 255 e, portanto, caberá em um byte.
Também preciso converter esse byte de volta nesse número. Como eu faria isso em Java? Já tentei de várias maneiras e nenhuma funcionou. Aqui está o que estou tentando fazer agora:
int size = 5;
// Convert size int to binary
String sizeStr = Integer.toString(size);
byte binaryByte = Byte.valueOf(sizeStr);
e agora para converter esse byte de volta no número:
Byte test = new Byte(binaryByte);
int msgSize = test.intValue();
Claramente, isso não funciona. Por algum motivo, ele sempre converte o número em 65
. Alguma sugestão?
Respostas:
Um byte é sempre assinado em Java. Você pode obter seu valor sem sinal binário-e-o com 0xFF, embora:
fonte
0xFF
resulta em um inteiro sem sinal? Alguma explicação seria muito útil.Java 8 oferece
Byte.toUnsignedInt
conversãobyte
paraint
conversão sem sinal. No JDK da Oracle, isso é implementado simplesmentereturn ((int) x) & 0xff;
porque o HotSpot já entende como otimizar esse padrão, mas pode ser intrinsecado em outras VMs. Mais importante, nenhum conhecimento prévio é necessário para entender o que faz uma chamadatoUnsignedInt(foo)
.No total, o Java 8 fornece métodos para converter
byte
eshort
para sem sinalint
elong
eint
para sem sinallong
. Um método para converterbyte
para não assinadoshort
foi omitido deliberadamente porque a JVM fornece apenas aritmética emint
e delong
qualquer maneira.Para converter uma volta int para um byte, é só usar um elenco:
(byte)someInt
. A conversão primitiva de estreitamento resultante descartará todos, exceto os últimos 8 bits.fonte
Se você só precisa converter um valor esperado de 8 bits de um int assinado em um valor não assinado, você pode usar o deslocamento de bits simples:
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/op3.html
Se estiver usando algo diferente de
int
tipo base, obviamente você precisará ajustar a quantidade de deslocamento: http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.htmlAlém disso, lembre-se de que você não pode usar o
byte
tipo, pois isso resultará em um valor com sinal, conforme mencionado por outros respondentes. O menor tipo primitivo que você poderia usar para representar um valor sem sinal de 8 bits seria ashort
.fonte
A
Integer.toString(size)
chamada é convertida na representação char do seu inteiro, ou seja, o char'5'
. A representação ASCII desse caractere é o valor 65.Você precisa analisar a string de volta para um valor inteiro primeiro, por exemplo, usando
Integer.parseInt
, para obter de volta o valor int original.Em
String
resumo , para uma conversão com / sem sinal, é melhor sair de cena e usar a manipulação de bits como @JB sugere.fonte
String sizeStr = Integer.toString(size); int sizeInt = Integer.parseInt(sizeStr); byte binaryByte = Byte.valueOf((byte) sizeInt);
String.getBytes()
produz os valores ASCII dos caracteres contidos no texto, não os valores numéricos dos dígitos. Você precisa analisar a string em um valor numérico, como sugeri acima.A solução funciona bem (obrigado!), Mas se você quiser evitar o lançamento e deixar o trabalho de baixo nível para o JDK, você pode usar um DataOutputStream para gravar seus int's e um DataInputStream para lê-los de volta. Eles são tratados automaticamente como não assinados bytes então:
Para converter int's em bytes binários;
Lendo-os de volta em:
Esp. útil para lidar com formatos de dados binários (por exemplo, formatos de mensagens simples, etc.)
fonte
Exceto
char
, todos os outros tipos de dados numéricos em Java são assinados.Como disse em uma resposta anterior, você pode obter o valor sem sinal executando uma
and
operação com0xFF
. Nesta resposta, vou explicar como isso acontece.Se sua máquina for de 32 bits, o
int
tipo de dados precisará de 32 bits para armazenar valores.byte
precisa de apenas 8 bits.A
int
variáveli
é representada na memória da seguinte maneira (como um inteiro de 32 bits).Então, a
byte
variávelb
é representada como:Como
byte
s não têm sinal, este valor representa-22
. (Pesquise o complemento de 2 para aprender mais sobre como representar inteiros negativos na memória)Então, se você lançar for para
int
, ainda assim será-22
porque o lançamento preserva o sinal de um número.O
32-bit
valor fundido deb
executarand
operação com0xFF
.Então você obtém
234
a resposta.fonte
Tratamento de bytes e inteiros sem sinal com BigInteger:
fonte
Embora seja tarde demais, gostaria de dar minha opinião sobre isso, pois pode esclarecer por que a solução fornecida por JB Nizet funciona. Eu me deparei com este pequeno problema trabalhando em um analisador de bytes e na conversão de strings. Quando você copia de um tipo integral de tamanho maior para um tipo integral de tamanho menor, pois este documento java diz que isso acontece:
https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.3 Uma conversão de estreitamento de um inteiro com sinal em um tipo integral T simplesmente descarta todos, exceto o n mais baixo bits de ordem, onde n é o número de bits usados para representar o tipo T. Além de uma possível perda de informação sobre a magnitude do valor numérico, isso pode fazer com que o sinal do valor resultante seja diferente do sinal do valor de entrada .
Você pode ter certeza de que um byte é um tipo integral, pois este documento java diz https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html byte: O tipo de dados de byte é um dois de 8 bits assinado complemento inteiro.
Portanto, no caso de converter um inteiro (32 bits) em um byte (8 bits), basta copiar o último (8 bits menos significativos) desse inteiro para a variável de byte fornecida.
A segunda parte da história envolve como os operadores unários e binários Java promovem operandos. https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.6.2 A conversão primitiva de ampliação (§5.1.2) é aplicada para converter um ou ambos os operandos, conforme especificado pelas seguintes regras:
Se um dos operandos for do tipo double, o outro será convertido em double.
Caso contrário, se um dos operandos for do tipo float, o outro será convertido para float.
Caso contrário, se um dos operandos for do tipo long, o outro será convertido em long.
Caso contrário, ambos os operandos são convertidos para o tipo int.
Fique tranquilo, se você estiver trabalhando com tipo integral int e / ou inferior, ele será promovido a int.
Também arranhei minha cabeça em torno disso :). Há uma boa resposta para isso aqui por rgettman. Operadores bit a bit em java apenas para inteiros e longos?
fonte
Se você quiser usar as classes de wrapper primitivas, isso funcionará, mas todos os tipos java são assinados por padrão.
fonte
em java 7
resultado: 254
fonte