Чтение байтов в Java

1

Я пытаюсь понять, как работает следующая строка кода:

for (int i = 0; i < numSamples; i++) {
        short ampValue = 0;
        for (int byteNo = 0; byteNo < 2; byteNo++) {
            ampValue |= (short) ((data[pointer++] & 0xFF) << (byteNo * 8));
        }
        amplitudes[i] = ampValue;
    }

Насколько я понимаю, это чтение 2 байтов (как 2 байта на выборку) включенным образом, то есть ampValue состоит из двух байтовых чтений. Данные представляют собой фактический образец данных (файл), и указатель увеличивается, чтобы прочитать его до последнего образца. Но я не понимаю эту часть:

"data[pointer++] & 0xFF) << (byteNo * 8)); "

Кроме того, мне интересно, не имеет значения, хочу ли я читать это как двойное, а не короткое?

  • 0
    Может ли endianness быть проблемой?
  • 0
    Я знаю, что это 16-битный формат с прямым порядком байтов ... но я не знаю много о порядке байтов или думаю, что это будет проблемой @huseyinTugrulBuyukisik
Показать ещё 1 комментарий
Теги:
type-conversion

3 ответа

0
Лучший ответ

Похоже, данные [] - это массив байтов.

data [pointer++] дает вам значение байта в диапазоне [-128.. 127].

0xFF является int contstant, поэтому...

data [pointer++] & 0xFF повышает значение байта до значения int в диапазоне [-128.. 127]. Затем оператор & обнуляет все биты, которые не установлены в 0xFF (т.е. он обнуляет 24 верхних бита, оставляя только низкие 8 бит.

Значение этого выражения теперь будет находиться в диапазоне [0..255].

Оператор << сдвигает результат влево на биты (byteNo * 8). То же самое, что и сказать, умножает значение на 2, поднятое до мощности (byteNo * 8). Когда byteNo == 0, он умножается на 2 на мощность 0 (т.е. Умножается на 1). Когда byteNo == 1, он умножается на 2 на мощность 8 (т.е. Умножается на 256).

Этот цикл создает int в диапазоне [0..65535] (16 бит) из каждой пары байтов в массиве, беря первый член каждой пары в качестве младшего байта, а второй член - как высокий байт.

Это не сработает, чтобы объявить ampValue как double, потому что оператор \= не будет работать с двойным, но вы можете объявить массив амплитуд [] как массив из двух, а amplitudes[i] = ampValue присваивания amplitudes[i] = ampValue будут неявно повысить значение до двойного значения в диапазоне [0.0..65535.0].


Дополнительная информация: Не забывайте комментарий @KevinKrumwiede об ошибке в примере.

  • 0
    Есть ли какой-то другой способ, которым я могу читать непосредственно из байтов как двойной, без использования оператора | =. Я нашел другой пример здесь: stackoverflow.com/questions/13024683/…
  • 0
    @NateRaswar, при условии, что ampValue правильно обнулено, тогда в этом конкретном случае оператор |= даст тот же ответ, что и += . | Оператор, который работает только с int-подобными значениями, дает вам побитовый или . Таким образом, бит n будет установлен в результате, если бит n в любом из операндов установлен. В этом конкретном случае математика работает так, что не будет перекрытия между двумя значениями, которые объединены вместе, поэтому побитовое или эффективное действие равнозначно добавлению двух операндов.
Показать ещё 1 комментарий
0

В Java все байты подписаны. Выражение (data[pointer++] & 0xFF) преобразует значение подписанного байта в int со значением байта, если оно было неподписанным. Тогда выражение << (byteNo * 8) сдвигает левое результирующее значение на ноль или восемь бит в зависимости от значения byteNo. Значение всего выражения назначается побитовым или ampValue.

В этом коде есть ошибка. Значение ampValue не сбрасывается до нуля между итерациями. И amplitude не используется. Являются ли эти идентификаторы одинаковыми?

  • 0
    да, амплитуда - ampValue, сразу исправлю!
0

Позвольте сломать выражение:

  • |= является побитовым и/или присваивающим оператором. a |= b эквивалентно a = a | b a = a | b.
  • (short) выводит элемент int из массива data на short.
  • pointer++ - операция с pointer++ приращением. Значение pointer будет возвращено и использовано, а затем сразу же будет увеличиваться каждый раз, когда он будет обращаться таким образом - это выгодно в этом случае, потому что внешний цикл циклически проходит через 2-байтовые выборки (через внутренний цикл) из смежных data буфера, поэтому он продолжает увеличиваться.
  • & является побитовым оператором И, а 0xFF является шестнадцатеричным значением для байта 0b11111111 (255 в десятичной 0b11111111); data[pointer++] & 0xFF выражения data[pointer++] & 0xFF в основном говорят, для каждого бита в байте, извлеченном из массива data, AND с 1. В этом контексте он заставляет Java, который по умолчанию хранит подписанные байтовые объекты (т.е. значения от -128 до 127 в десятичном формате), чтобы вернуть значение в виде байта без знака (т.е. значения от 0 до 255 десятичных знаков).
  • Поскольку ваши образцы имеют длину 2 байта, вам нужно сдвинуть вторую партию из 8 бит влево, как наиболее значимые биты, используя левый оператор смещения бит <<. byteNo * 8 гарантирует, что вы только сдвигаете биты, когда это второй из двух байтов.

После того, как два байта будут прочитаны, ampValue теперь будет содержать значение образца как short.

  • 0
    только что исправил ошибку, ampValue должен был быть амплитудой. Это имеет смысл сейчас. Тем не менее, вы знаете, как я могу прочитать это как двойной? В Eclipse говорится, что оператор | = не определен для типа double!
  • 0
    «(короткий) преобразует (предположительно) байтовый объект из массива данных в короткий« Нет, значение, которое преобразуется в (короткий), является (int) значением. Байты из массива преобразуются в (int), когда они побитовым образом добавляются с константой (int), 0xFF.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню