Побитовое И, Побитовое включение вопроса ИЛИ, в Java

У меня есть несколько строк кода внутри проекта, что я не вижу значения...

buffer[i] = (currentByte & 0x7F) | (currentByte & 0x80);

Он считывает файлбуфер из файла, сохраняется как байты, а затем передает затем в буфер [i], как показано, но я не могу понять, какова общая цель, какие-либо идеи?

Спасибо

Ответ 1

Как уже было сказано, (currentByte & 0x7F) | (currentByte & 0x80) эквивалентен (currentByte & 0xFF). JLS3 15.22.1 говорит, что это продвигается до int:

Когда оба операнда оператора &, ^, или | имеют тип, который кабриолет (§5.1.8) к примитивному интегральный тип, двоичный числовой продвижение сначала выполняется на операндов (§5.6.2). Тип побитовое выражение оператора поддерживаемый тип операндов.

потому что JLS3 5.6.2 говорит, что когда currentByte имеет тип byte и 0x7F - это int (и это это так), то оба операнда продвигаются до int.

Следовательно, buffer будет массивом типа элемента int или более широким.

Теперь, выполнив & 0xFF в int, мы эффективно сопоставим исходный диапазон byte -128..127 в неподписанном диапазоне 0..255, операцию, часто используемую потоками java.io, например.

Вы можете увидеть это в действии в следующем фрагменте кода. Обратите внимание, что для понимания того, что здесь происходит, вы должны знать, что Java хранит интегральные типы, кроме char, как 2 дополнения.

byte b = -123;
int r = b;
System.out.println(r + "= " + Integer.toBinaryString(r));
int r2 = b & 0xFF;
System.out.println(r2 + "= " + Integer.toBinaryString(r2));

Наконец, для примера в реальном мире проверьте Javadoc и реализацию метода read 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;
}

Ответ 2

 (currentByte & 0x7F) | (currentByte & 0x80)

эквивалентно

 currentByte & (0x7F | 0x80)

который равен

 currentByte & 0xFF

что точно совпадает с

 currentByte

Изменить: я только посмотрел на правую часть задания, и я все еще думаю, что эквивалентность истинна.

Однако, похоже, что код хочет передать подписанный байт более крупному типу при интерпретации байта как unsigned.

Есть ли более простой способ для перевода подписанного байта в unsigned в java?

Ответ 3

Я думаю, что кто-то слишком много думал здесь. Это просто не так.

У меня есть только одно замечание

  • Исходный автор беспокоился о том, что время выполнения заменяет байта на собственное целое число со знаком (предположительно 32-битное) и явно пытается рассказать нам что-то о том, что бит знака является "особенным"?

Этот код остался позади. Разве вы не знаете, что вы в рыбной перспективе? Какой тип "буфера" в любом случае?

Ответ 4

Сложная побитовая логика совершенно лишняя.

for (int i = 0; i < buffer.length; i++) {
    buffer[i] = filebuffer[currentPosition + i] & 0xff;
}

делает то же самое. Если буфер объявлен как массив байтов, вы можете даже оставить и 0xff, но, к сожалению, декларация не отображается.

Причина может заключаться в том, что первоначальный разработчик был смущен байтами, подписанными в Java.

Ответ 5

Результат побитовой операции И имеет 1 на этих битах, где оба бита равны 1, в то время как результат побитового ИЛИ операции hase a на битах, где один из бит-бит равен 1.

Итак, пример оценки для значения 0x65:

  01100101 0x65
& 01111111 0x7F
===============
  01100101 0x65

  01100101 0x65
& 10000000 0x80
===============
  00000000 0x00

  01100101 0x65
| 00000000 0x00
===============
  01100101 0x65

Ответ 6

Хорошая вещь об этих типах логических операций: вы можете попробовать каждую возможную комбинацию (все 256 из них) и убедиться, что вы получите ответ, который вы ожидали.

Ответ 7

Оказывается, файл, который был прочитан байтом, был в битвой нотации со знаком и другой длины, поэтому было поручено выполнить эту задачу, чтобы позволить ей быть расширенным до типа java int, сохраняя при этом его правильный знак:)