Bitstring

Bitstring is a pure Python module designed to help make the creation and analysis of binary data as simple and natural as possible. The documentation is really good and this page limits itself to some quick examples.


In [1]:
import bitstring

Basics

There are four basic classes for representing binary data: Bits, BitArray, ConsBitStream and BitStream. Each has advantages and disadvantages but for most applications BitArray will be a good choice.


In [2]:
from_hex = bitstring.BitArray('0x0001b3')
from_bin = bitstring.BitArray('0b001100')
from_oct = bitstring.BitArray('0o34100')
from_int = bitstring.BitArray(uint=45, length=8)
from_int_bigendian = bitstring.BitArray(intbe=-32768, length=16)
from_float = bitstring.BitArray(float=10.3, length=32)                     # floats must be 32 or 64 bits long
from_float_littleendian = bitstring.BitArray(floatle=-273.15, length=64)   # floats must be 32 or 64 bits long
from_raw = bitstring.BitArray(bytes=b'\x00\x01\x02\xff', length=28)
from_bool = bitstring.BitArray(True)

In [3]:
from_hex, from_bin, from_oct, from_int, from_int_bigendian, from_float, from_float_littleendian, from_raw, from_bool


Out[3]:
(BitArray('0x0001b3'),
 BitArray('0b001100'),
 BitArray('0b011100001000000'),
 BitArray('0x2d'),
 BitArray('0x8000'),
 BitArray('0x4124cccd'),
 BitArray('0x66666666661271c0'),
 BitArray('0x000102f'),
 BitArray('0b0'))

Converting to a different format


In [4]:
from_int.bin, from_int.bytes, from_int.uint, from_int.int, from_int.hex, from_float_littleendian.floatbe


Out[4]:
('00101101', b'-', 45, 45, '2d', 1.9035985645941102e+185)

Lengths, slicing and joining


In [5]:
len(from_bool), len(from_float)


Out[5]:
(1, 32)

In [6]:
from_int[-4:].bin, from_int[:4].int


Out[6]:
('1101', 2)

In [7]:
from_hex + from_int


Out[7]:
BitArray('0x0001b32d')

Non-byte aligned binary data

This only works for some data types!


In [16]:
seven_bits = bitstring.BitArray(int=32, length=7)
len(seven_bits), seven_bits.bin


Out[16]:
(7, '0100000')

In [18]:
seven_bits.tobytes()     # tobytes() ensures padding to byte-alignment


Out[18]:
b'@'

Packing and unpacking

Packing and unpacking is particularly useful for creating "compound" binary data.


In [10]:
packed = bitstring.pack('bool, int:7, floatbe:32', True, -32, -273.15)
len(packed), packed.bin, packed.bytes


Out[10]:
(40, '1110000011000011100010001001001100110011', b'\xe0\xc3\x88\x933')

In [11]:
packed.unpack('bool, int:7, floatbe:32')


Out[11]:
[True, -32, -273.1499938964844]

Finding and replacing


In [12]:
list(packed.find('0b0000')), list(packed.findall('0b0000'))


Out[12]:
([3], [3, 4, 10])

In [13]:
packed.replace('0b0000', '0b1111')
packed.bin


Out[13]:
'1111111011111111100010001001001100110011'

In [14]:
packed.startswith('0b111'), packed.endswith('0b111')


Out[14]:
(True, False)

Bit-operations


In [15]:
a = bitstring.BitArray('0b00001111')
b = bitstring.BitArray('0b01010101')
(a).bin, (~a).bin, (a<<2).bin, (a>>2).bin, (a*2).bin, (a&b).bin, (a|b).bin, (a^b).bin


Out[15]:
('00001111',
 '11110000',
 '00111100',
 '00000011',
 '0000111100001111',
 '00000101',
 '01011111',
 '01011010')

In [ ]: