Bit a bit E, bit a bit Inclusive ou pergunta, em Java
-
05-09-2019 - |
Pergunta
Eu tenho algumas linhas de código dentro de um projeto, que eu não posso ver o valor de ...
buffer[i] = (currentByte & 0x7F) | (currentByte & 0x80);
Ele lê o filebuffer de um arquivo, armazenados como bytes, e depois transfere depois para buffer [i] como mostrado, mas eu não consigo entender o que o objectivo global é, todas as idéias?
Graças
Solução
Como as outras respostas já foi dito, (currentByte & 0x7F) | (currentByte & 0x80)
é equivalente a (currentByte & 0xFF)
. O JLS3 15.22.1 diz que esta é promovida a um int
:
Quando ambos os operandos de um operador e, ^ Ou | são de um tipo que é convertível (§5.1.8) a uma primitiva tipo integral, numérico binário promoção é realizada pela primeira vez na operandos (§5.6.2). O tipo do expressão operador bit a bit é a Tipo promovido dos operandos.
5.6.2 diz que quando currentByte
tem tipo byte
e 0x7F
é um int
(e este é o caso), então ambos os operandos são promovidos a int
.
Portanto, buffer
será uma matriz de elemento tipo int
ou mais larga.
Agora, através da realização de & 0xFF
em um int
, nós efetivamente mapear a gama byte
originais -128..127 para a faixa sem assinatura 0..255, uma operação muitas vezes utilizados por java.io
córregos por exemplo.
Você pode ver isso em ação no seguinte trecho de código. Note-se que para entender o que está acontecendo aqui, você tem que saber que armazena Java tipos integrais, exceto char
, como complemento de 2 valores.
byte b = -123;
int r = b;
System.out.println(r + "= " + Integer.toBinaryString(r));
int r2 = b & 0xFF;
System.out.println(r2 + "= " + Integer.toBinaryString(r2));
Finalmente, para um exemplo do mundo real, confira o Javadoc e implementação do método read
de java.io.ByteArrayInputStream
:
/**
* Reads the next byte of data from this input stream. The value
* byte is returned as an <code>int</code> in the range
* <code>0</code> to <code>255</code>. If no byte is available
* because the end of the stream has been reached, the value
* <code>-1</code> is returned.
*/
public synchronized int read() {
return (pos < count) ? (buf[pos++] & 0xff) : -1;
}
Outras dicas
(currentByte & 0x7F) | (currentByte & 0x80)
é equivalente a
currentByte & (0x7F | 0x80)
o que equivale
currentByte & 0xFF
que é exatamente o mesmo que
currentByte
Edit:. Eu só olhei para o lado direito da atribuição, e eu ainda acho que o equivalance é verdade
No entanto, parece que o código quer lançar o byte assinado para um tipo maior ao interpretar o byte como sem assinatura.
Existe uma maneira mais fácil de elenco assinou-byte para unsigned em java?
Eu acho que alguém fez pensar muito aqui. Isso simplesmente não é certo.
Eu tenho mas uma observação
- O autor original estava preocupado com o tempo de execução substituindo o byte com um inteiro assinado nativa (provavelmente 32-bit) e é explicitamente tentando nos dizer algo sobre o sinal mordeu ser "especial"?
É o código deixado para trás. A menos que você sabe que está em um tempo de execução de peixe? Qual é o tipo do 'buffer' de qualquer maneira?
A lógica bit a bit complicado é completamente supérfluo.
for (int i = 0; i < buffer.length; i++) {
buffer[i] = filebuffer[currentPosition + i] & 0xff;
}
faz a mesma coisa. Se buffer é declarado como um array de bytes que você pode até mesmo deixar de fora o & 0xff, mas, infelizmente, a declaração não é mostrado.
A razão pode ser que o desenvolvedor original foi confundido por bytes a ser assinado em Java.
O resultado de uma operação AND tem um 1 em que os bits onde ambos os bits são 1, enquanto o resultado de uma operação OR hase um em que os bits onde qualquer um de bits Bot é 1.
Assim, um exemplo de avaliação para o valor 0x65:
01100101 0x65
& 01111111 0x7F
===============
01100101 0x65
01100101 0x65
& 10000000 0x80
===============
00000000 0x00
01100101 0x65
| 00000000 0x00
===============
01100101 0x65
A boa coisa sobre esses tipos de operações lógicas:. Você pode tentar todas as combinações possíveis (todos 256 deles) e verificar se você obter a resposta que você esperava
Acontece que, o arquivo que o byte foi sendo lidos estava em uma notação bit assinado, e de um comprimento diferente, pois foi requried para executar esta tarefa para permitir que ele seja estendido para o tipo int java, mantendo seu sinal correto:)