Страницы

Поиск по вопросам

пятница, 31 января 2020 г.

Получение битов из байтов

#java #android #byte #bit


Например есть 8 байт данных.
Есть стартовый байт и стартовый бит - откуда нужно взять информацию, а также длина
в битах(сколько нужно взять).

Как я могу достать из этих 8 байт например, с первого байта - 7 и 8 бит (т.е. стартовый
байт №1, позиция стартового бита №7, длина 2 бита)

или например, с 3го бита второго байта взять 14 бит (то есть используется второй
и третий байт)
    


Ответы

Ответ 1



Для того чтобы не "воевать" самому с битовыми операциями, можно воспользоваться стандартным классом BitSet: public static BitSet getBitSet(byte[] array, int fromByteIndex, int fromByteBitIndex, int bitsCount) { BitSet arrayBitSet = BitSet.valueOf(array); int fromIndex = fromByteIndex * 8 + fromByteBitIndex; return arrayBitSet.get(fromIndex, fromIndex + bitsCount); } И использование: byte[] array = { 10, 1, 127 }; BitSet result = getBitSet(array, 1, 7, 2); System.out.println(result.get(0)); System.out.println(result.get(1)); false true В BitSet индексы битов определяются так: 10 = 00001010 76543210 - индексы Если нужен обратный порядок: 10 = 00001010 01234567 - индексы то, как вариант, можно предварительно менять порядок битов в байтах: public static BitSet getBitSet(byte[] array, int fromByteIndex, int fromByteBitIndex, int bitsCount) { byte[] reversedBitsOrderArray = new byte[array.length]; for (int i = 0; i < array.length; i++) { reversedBitsOrderArray[i] = reverseBitsOrder(array[i]); } BitSet arrayBitSet = BitSet.valueOf(reversedBitsOrderArray); int fromIndex = fromByteIndex * 8 + fromByteBitIndex; return arrayBitSet.get(fromIndex, fromIndex + bitsCount); } private static byte reverseBitsOrder(byte b) { byte from = b; byte to = 0; for (int i = 0; i < 8; i++) { to <<= 1; to |= (from & 1); from >>= 1; } return to; } В принципе, в этом случае решение "взять биты вручную" становится короче и проще: public static boolean[] getBits(byte[] array, int fromByteIndex, int fromByteBitIndex, int bitsCount) { boolean[] bits = new boolean[bitsCount]; int fromIndex = fromByteIndex * 8 + fromByteBitIndex; for (int i = 0; i < bitsCount; i++) { int byteIndex = (i + fromIndex) / 8; int bitIndex = (i + fromIndex) % 8; bits[i] = (array[byteIndex] & (1 << (7 - bitIndex))) != 0; } return bits; }

Ответ 2



Как это устроено "под капотом": public static boolean getBitFromByte(byte b, int position) { // position = 6 - т.е. хотим получить 7 бит // 11010110 - b // & - побитовая операция И // 01000000 == (1 << 6) - сдвиг влево на 6 позиций (битов) // = // 01000000 // затем сдвигаем обратно на 6 позиций вправо: // 01000000 >> 6 == 00000001 - что означает 7-й бит // данного байта b равен 1 (единице) return ((b & (1 << position)) >> position) == 1; } public static boolean getBitFromBytes(byte[] bs, int bytePos, int bitPos) { return getBitFromByte(bs[bytePos], bitPos); } public static byte setBitInByte(byte b, boolean bit, int position) { if (bit) return (byte)(b | (1 << position)); else return (byte)(b & ~(1 << position)); } // почему-то нельзя преобразовать в Java тип boolean к int, не используя условие // поэтому приходится передавать установочный бит в типе int public static byte setBitInByteFast(byte b, int bit, int position) { return (byte) (((1 - bit) * ~0) ^ ((((1 - bit) * ~0) ^ b) | (1 << position))); } public static void main( String[] args ) { byte b = 0; b = setBitInByte(b, true, 3); System.out.println(getBitFromByte(b, 3)); b = setBitInByte(b, false, 3); System.out.println(getBitFromByte(b, 3)); b = setBitInByteFast(b, 1, 3); System.out.println(getBitFromByte(b, 3)); b = setBitInByteFast(b, 0, 3); System.out.println(getBitFromByte(b, 3)); }

Ответ 3



Используйте побитовый AND: byte[] bytes = {-1,2,3,4,5,6,7,8}; System.out.println((bytes[0] & 0x80) == 0x80); // 0x80 - 1000 0000 в двоичном коде System.out.println((bytes[0] & 0x40) == 0x40); // 0x40 - 0100 0000 в двоичном коде Результат: true true

Комментариев нет:

Отправить комментарий