从字节数组中提取位

时间:2016-10-20 13:32:38

标签: java arrays bit-manipulation byte bit

我想从字节数组中提取位级编码的信息。 假设我的模型类似于

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

我有一个包含4个字节的数组,我怎么能将我的模型与我的数组匹配?

我读了一些关于位操作的帖子,但我并不确定已经理解了所有内容。

1 个答案:

答案 0 :(得分:0)

我发现了BitSet对象,这似乎对我想做的事情非常有用。

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;
    }
}

通过这个类,我可以逐位解码字节数组。

我不知道这是否是最好的解决方案,但这可以做我想要的。