Например есть 8 байт данных. Есть стартовый байт и стартовый бит - откуда нужно взять информацию, а также длина в битах(сколько нужно взять).
Как я могу достать из этих 8 байт например, с первого байта - 7 и 8 бит (т.е. стартовый байт №1, позиция стартового бита №7, длина 2 бита)
или например, с 3го бита второго байта взять 14 бит (то есть используется второй и третий байт)
Для того чтобы не "воевать" самому с битовыми операциями, можно воспользоваться стандартным классом 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;
}
Как это устроено "под капотом":
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));
}
Используйте побитовый 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
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Не могу понять в чём проблемаOpenJpa выдаёт такую ошибку:
Адаптирую сайт под мобильные телефоны, столкнулся с такой проблемой что navbar который идет в примерах bootstrap невероятно малПриходиться на телефоне...
Я пытаюсь сделать так, чтобы текст был слева и имел позицию float left, а ссылки принимали значения float right, но ссылки не принимают этого значенияЯ...