0

I would like to extract information encoded at a bit level from a byte array. Assuming that my model is something like

Model
Field 1 - 3 bits
Field 2 - 7 bits
Field 3 - 9 bits
Field 4 - 13 bits

And i've got an array containing 4 bytes, how could i match my model with my array ?

I read some posts about bit manipulation but i'm not really sure to have understood everything.

6
  • Where's your code? If you read "some posts" then you knew which operators to use. Commented Oct 20, 2016 at 13:35
  • Hard to answer without you saying what type the fields are, but speaking generally, it sounds like a BitSet does what you want. Commented Oct 20, 2016 at 13:43
  • All fields are int. I read some posts but as I said i din't understand everything about what I read. Especially about masks. Commented Oct 20, 2016 at 13:48
  • 1
    With that level of info, what could we answer that isn't already in the things you've read? If all we have to go on is "I don't understand it," we can't give more than"here's how it generally works," which you've already read. This is unfortunately too broad for SO. Commented Oct 20, 2016 at 13:51
  • I was expecting an explanation, a new formulation. Since i read how it generally works without understanding it, I was thinking that a new explanation of how it generally works would be nice. Commented Oct 20, 2016 at 14:43

1 Answer 1

2

I found out BitSet object, which seems to be really useful for what i want to do.

public class BytesDecoder {

    private BitSet bitSetToDecode;

    /**
     * BytesDecoder constructor
     * Init the BitSet used for decoding
     * @param bytes the byte array to decode
     */
    public BytesDecoder(byte[] bytes) {
        Log.i("BytesDecoder", "==== FRAME TO DECODE ====");
        Log.i("BytesDecoder", Arrays.toString(bytes));
        // Translate bytes array as binary
        String frameBinary ="";
        for (byte b : bytes) {
            frameBinary  += toBinary(b,8);
        }
        Log.i("BytesDecoder", frameBinary);

        // Init the BitSet with an array of reversed bytes to handle the little endian representation expected
        bitSetToDecode = BitSet.valueOf(reverse(bytes));
    }

    /**
     * Decode a part of the byte array between the startIndex and the endIndex
     * @param startIndex index of the first bit to include
     * @param endIndex index after the last bit to include
     * @return the int value of the decoded bits
     */
    public int decode(int startIndex, int endIndex) {
        int length = endIndex - startIndex;

        int decodedInt = convert(bitSetToDecode.get(startIndex, endIndex), length);

        Log.i("BytesDecoder","--- Decoded parameter --- ");
        Log.i("BytesDecoder",toBinary(decodedInt, length) + " interpreted as " + decodedInt);

        return decodedInt;
    }

    /**
     * Reverse bit order of each byte of the array
     * @param data the bytes array
     * @return the bytes array with bit order reversed for each byte
     */
    private byte[] reverse(byte [] data) {
        byte [] bytes = data.clone();

        for (int i = 0; i < bytes.length; i++) {
            bytes[i] = (byte) (Integer.reverse(bytes[i]) >>> 24);
        }

        return bytes;
    }

    /**
     * Get the binary form of an int
     * @param num the int number
     * @param length the bit length
     * @return the string value of the binary form of the int
     */
    private String toBinary(int num, int length) {
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < length; i++) {
            sb.append(((num & 1) == 1) ? '1' : '0');
            num >>= 1;
        }

        return sb.reverse().toString();
    }

    /**
     * Convert a BitSet into an int
     * @param bits the BitSet
     * @param length the BitSet theorical lenght
     * @return the int value corresponding
     */
    private int convert(BitSet bits, int length) {
        int value = 0;
        // Set the increment to the difference between the therocial length and the effective lenght of the bitset
        // to take into account the fact that the BitSet just represent significative bits
        // (i.e instead of 110, the bitset while contains 11 since the 0 is irrelevant in his representation)
        int increment = length - bits.length();

        // Browse the BitSet from the end to the begining to handle the little endian representation
        for (int i = bits.length() - 1; i >= 0; --i) {
            value += bits.get(i) ? (1L << increment) : 0L;
            increment++;
        }

        return value;
    }
}

With this class, I can decode a byte array bit by bit.

I don't know if it's the best solution, but this do what i wanted.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.