Estou tentando converter um byte assinado em não assinado. O problema é que os dados que estou recebendo não são assinados e o Java não suporta byte não assinado; portanto, quando lê os dados, trata-os como assinados.
Tentei convertê-lo pela seguinte solução que obtive do Stack Overflow.
public static int unsignedToBytes(byte a)
{
int b = a & 0xFF;
return b;
}
Mas quando é convertido novamente em byte, recebo os mesmos dados assinados. Estou tentando usar esses dados como um parâmetro para uma função de Java que aceita apenas um byte como parâmetro, portanto, não posso usar nenhum outro tipo de dados. Como posso resolver este problema?
Respostas:
Não sei se entendi sua pergunta.
Eu apenas tentei isso e para o byte -12 (valor assinado) ele retornou o número inteiro 244 (equivalente ao valor do byte não assinado, mas digitado como um
int
):É o que você quer fazer?
Java não permite expressar 244 como um
byte
valor, como seria C. Para expressar números inteiros positivos acimaByte.MAX_VALUE
(127), você deve usar outro tipo de número inteiro, comoshort
,int
oulong
.fonte
byte b = (byte)unsignedToBytes((byte) -12);
Agora tente imprimir bO fato de as primitivas serem assinadas em Java é irrelevante para como elas são representadas na memória / trânsito - um byte é de apenas 8 bits e se você interpreta isso como um intervalo assinado ou não, é com você. Não há sinalizador mágico para dizer "isto está assinado" ou "isto não está assinado".
Como as primitivas são assinadas, o compilador Java impedirá que você atribua um valor maior que +127 a um byte (ou menor que -128). No entanto, não há nada para impedir que você faça downcast de um int (ou curto) para conseguir isso:
fonte
Guia completo para trabalhar com bytes não assinados em Java:
Byte não assinado em Java
(Fonte para esta resposta.)
A linguagem Java não fornece nada parecido com a
unsigned
palavra - chave. A debyte
acordo com a especificação da linguagem representa um valor entre -128 - 127. Por exemplo, se abyte
for convertido para umint
Java, ele interpretará o primeiro bit como sinal e usará a extensão de sinal .Dito isto, nada impede que você veja
byte
apenas 8 bits e interprete esses bits como um valor entre 0 e 255. Lembre-se de que não há nada que você possa fazer para forçar sua interpretação sobre o método de outra pessoa. Se um método aceitar umbyte
, esse método aceita um valor entre -128 e 127, a menos que seja explicitamente indicado o contrário.Aqui estão algumas conversões / manipulações úteis para sua conveniência:
Conversões de / para int
(Ou, se você estiver no Java 8 ou superior, use
Byte.toUnsignedInt
.)Análise / formatação
A melhor maneira é usar as conversões acima:
Aritmética
A representação de 2 complementos "simplesmente funciona" para adição, subtração e multiplicação:
A divisão requer conversão manual de operandos:
fonte
Não há bytes não assinados primitivos em Java. O normal é convertê-lo para um tipo maior:
fonte
Acho que as outras respostas cobriram a representação da memória e como você lida com isso depende do contexto de como planeja usá-la. Acrescentarei que o Java 8 adicionou algum suporte para lidar com tipos não assinados . Nesse caso, você poderia usar
Byte.toUnsignedInt
fonte
Uma nota lateral, se você quiser imprimi-lo, basta dizer
fonte
println(b & 0xff)
é suficienteSe acha que está procurando algo assim.
fonte
Adamski forneceu a melhor resposta, mas ela não está completa, então leia sua resposta, pois explica os detalhes que não estou.
Se você possui uma função do sistema que requer que um byte não assinado seja passado para ele, você pode transmitir um byte assinado, pois ele o tratará automaticamente como um byte não assinado.
Portanto, se uma função do sistema exigir quatro bytes, por exemplo, 192 168 0 1 como bytes não assinados, você poderá passar -64 -88 0 1, e a função ainda funcionará, porque o ato de passá-los para a função os cancelará a assinatura .
No entanto, é improvável que você tenha esse problema, pois as funções do sistema estão ocultas atrás das classes para compatibilidade entre plataformas, embora alguns dos métodos de leitura java.io retornem bytes não suspirados como int.
Se você quiser ver isso funcionando, tente escrever bytes assinados em um arquivo e leia-os novamente como bytes não assinados.
fonte
Você também pode:
Explicação:
Digamos
a = (byte) 133;
Na memória, é armazenado como: "1000 0101" (0x85 em hex)
Portanto, sua representação traduz não assinado = 133, assinado = -123 (como complemento de 2)
Quando o deslocamento para a esquerda é executado 24 bits para a esquerda, o resultado é agora um número inteiro de 4 bytes, representado como:
"10000101 00000000 00000000 00000000" (ou "0x85000000" em hexadecimal)
então nós temos
e muda novamente à direita 24 bits, mas é preenchido com zeros à esquerda. Portanto, resulta em:
"00000000 00000000 00000000 10000101" (ou "0x00000085" em hexadecimal)
e essa é a representação não assinada que é igual a 133.
Se você tentou transmitir
a = (int) a;
, o que aconteceria é manter a representação do byte do complemento 2 e armazená-lo como int também como o complemento do 2:(int) "10000101" ---> "11111111 11111111 11111111 10000101"
E isso se traduz como: -123
fonte
java.lang.Byte.toUnsignedInt(byte value)
. E se você ainda não estiver usando o Java 8, atualize o mais rápido possível. O Java 7 e versões anteriores estão em fim de vida.Isso não é substancialmente diferente de uma função que aceita um número inteiro para o qual você deseja passar um valor maior que 2 ^ 32-1.
Parece que depende de como a função é definida e documentada; Eu posso ver três possibilidades:
Pode documentar explicitamente que a função trata o byte como um valor não assinado; nesse caso, a função provavelmente deve fazer o que você espera, mas parece estar implementada incorretamente. Para o caso inteiro, a função provavelmente declararia o parâmetro como um inteiro não assinado, mas isso não é possível para o caso de byte.
Ele pode documentar que o valor desse argumento deve ser maior que (ou talvez igual a) zero; nesse caso, você está fazendo mau uso da função (passando um parâmetro fora do intervalo), esperando que faça mais do que foi projetado para Faz. Com algum nível de suporte à depuração, você pode esperar que a função gere uma exceção ou falhe em uma asserção.
A documentação pode não dizer nada; nesse caso, um parâmetro negativo é, bem, um parâmetro negativo e se isso tem algum significado depende do que a função faz. Se isso não faz sentido, talvez a função deva realmente ser definida / documentada como (2). Se isso for significativo de uma maneira não óbvia (por exemplo, valores não negativos são usados para indexar em uma matriz, e valores negativos são usados para indexar de volta a partir do final da matriz, então -1 significa o último elemento) a documentação deve dizer o que significa e eu esperaria que não é o que você quer fazer de qualquer maneira.
fonte
Se você tem uma função que deve receber um byte assinado, o que você espera que faça se passar um byte não assinado?
Por que você não pode usar outro tipo de dados?
Desnecessariamente, você pode usar um byte como um byte não assinado com traduções simples ou sem traduções. Tudo depende de como é usado. Você precisaria esclarecer o que pretende fazer com isso.
fonte
Embora possa parecer irritante (vindo de C) que Java não tenha incluído byte não assinado na linguagem, isso não é grande coisa, pois uma operação simples "b & 0xFF" gera o valor não assinado para o byte (assinado) b no (raro) situações em que é realmente necessário. Na verdade, os bits não mudam - apenas a interpretação (que é importante apenas ao realizar, por exemplo, algumas operações matemáticas nos valores).
fonte
x & 0xFF
qualquer lugar que precisar ou repete algo como embehaveLikeAnUnsignedByte(x)
qualquer lugar. Isso é necessário para cada local em que você usa um valor de bytes ou uma matriz de bytes que precisa ser sem sinal; não há maneira concebível de evitar essa repetição. Você não pode escrever a implementação de um protocolo que lê e grava valores de bytes com apenas uma única referência a uma variável de bytes. Sua visão simplista pode explicar por que eles nunca se importaram em corrigi-lo.Não há byte não assinado em Java, mas se você deseja exibir um byte, pode fazê-lo,
Resultado:
Para obter mais informações, consulte Como exibir um valor hex / byte em Java .
fonte
java.lang.Byte.toUnsignedInt(byte value);
existe para isso.Conforme as limitações em Java, o byte não assinado é quase impossível no formato de tipo de dados atual. Você pode procurar outras bibliotecas de outro idioma para o que está implementando e, em seguida, chamá-las usando JNI .
fonte
Sim e não. Eu tenho procurado por esse problema. Como eu entendo isso:
O fato é que java assinou o interger -128 a 127. É possível apresentar um não assinado em java com:
Se, por exemplo, você adicionar um número -12 assinado para não assinar, obtém 244. Mas você pode usar esse número novamente em um sinal assinado, ele deve ser alterado novamente para sinalizado e será novamente -12.
Se você tentar adicionar 244 ao java byte, obterá outOfIndexException.
Felicidades..
fonte
java.lang.Byte.toUnsignedInt(byte value);
existe para isso.Se você deseja bytes não assinados em Java, basta subtrair 256 do número em que está interessado. Isso produzirá o complemento de dois com um valor negativo, que é o número desejado em bytes não assinados.
Exemplo:
Você precisa usar hacks sujos ao usar o leJOS para programar o bloco NXT .
fonte
speed_unsigned
é assinado. Imprima e veja. (E o que- 256
não alcança nada aqui.)