Как записывать и читать отдельные биты из байта

154
25 марта 2019, 02:40

Допустим у меня есть байт, и в нем я хочу хранить 8 boolean'ов. Как мне читать и записывать отдельные биты в байт? Пожалуйста без битсета, я хочу понять это.

Answer 1

Нужно учитывать, что в Java при использовании побитовых операторов с типами byte и short, происходит расширение до int. Поэтому проще и нагляднее использование int для хранения 32 boolean'ов:

BooleanInIntHolder.java

public class BooleanInIntHolder {
    //Initial "filter mask" - "1000 0000 0000 0000 0000 0000 0000 0000"
    private static final int INITIAL_BIT_MASK = -2147483648;
    private static final int FIRST_BOOLEAN_ADDRESS = 0;
    private static final int LAST_BOOLEAN_ADDRESS = 31;
    private int booleanHolder;
    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        for (int i = FIRST_BOOLEAN_ADDRESS; i <= LAST_BOOLEAN_ADDRESS; i++) {
            builder.append(i)
                   .append(" = ")
                   .append(booleanAt(i))
                   .append("\n");
        }
        return builder.toString();
    }
    public void setTrue(int booleanAddress) {
        int bitMask = createBitMask(booleanAddress);
        // Perform bitwise OR to set 1(true) at required address (X OR 1 = 1)
        // Without affecting other bits
        // For example:
        // 0010 0000 ... - bitMask
        // |             - bitwise OR
        // XXXX XXXX ... - current booleanHolder
        // =
        // XX1X XXXX ... - result (other bits didn't affect)
        booleanHolder = bitMask | booleanHolder;

    }
    public void setFalse(int booleanAddress) {
        int bitMask = createBitMask(booleanAddress);
        // Perform bitwise NOT for bitMask
        // For example from "0010 0000" we get "1101 1111"
        bitMask = ~bitMask;
        // Perform bitwise AND to set 0(false) at required address (X AND 0 = 0)
        // Without affecting other bits
        // For example:
        // 1101 1111 ... - bitMask
        // &             - bitwise AND
        // XXXX XXXX ... - current booleanHolder
        // 
        // XX0X XXXX ... - result (other bits didn't affect)
        booleanHolder =  bitMask & booleanHolder; 
    }
    public boolean booleanAt(int booleanAddress) {
        int bitMask = createBitMask(booleanAddress);
        // We don't check other bits so set them to 0
        // For example, if boolean address is 2
        // XXXX XXXX ... - current booleanHolder
        // &             - (X AND 1 = X)
        // 0010 0000 ... - bitMask
        // =
        // 00X0 0000 ... - filteredBooleanHolder
        int filteredBooleanHolder = bitMask & booleanHolder;
        // If (filteredBooleanHolder != 0) => X is 1 => true
        return (!(filteredBooleanHolder == 0));
    }

    // Create bitMask "1000 0000 ..."
    // And tune it to filter required address - move filter bit(1) right
    // Use unsigned right shift(>>>) because first bit is "sign bit"
    // For example, if booleanAddress is 2, we need "0010 0000" mask 
    private int createBitMask(int booleanAddress) {
        if (booleanAddress < FIRST_BOOLEAN_ADDRESS || booleanAddress > LAST_BOOLEAN_ADDRESS) {
            throw new IllegalArgumentException("Illegal boolean address" + booleanAddress);
        }
        int bitMask = INITIAL_BIT_MASK;
        bitMask >>>= booleanAddress;
        return bitMask;
    }
}

BooleanHolderTester.java

public class BooleanHolderTester {
    public static void main(String args[]) {
        BooleanInIntHolder booleanHolder = new BooleanInIntHolder();
        for (int i = 0; i <= 7; i += 2) {
            booleanHolder.setTrue(i);
        }
        System.out.println(booleanHolder);
        booleanHolder.setFalse(0);
        System.out.println(booleanHolder);
        booleanHolder.setFalse(4);
        System.out.println(booleanHolder);
    }
}
READ ALSO
Разное выравнивание на разных экранах

Разное выравнивание на разных экранах

Есть 2 блока которые на больших экранах нужно отобразить в один ряд с выравниванием содержимого по левому краю, а на маленьких в два ряда и с выравниванием...

169
Не работают события [закрыт]

Не работают события [закрыт]

Почему в данном примере консоль выдаёт ошибку?

167