Python bitstring模块介绍

 

一、bitstring简介

  A Python module to help you manage your bits。

  这是一个便于管理bit的Python模块,其方便性在于借鉴Python中字符串和列表的特性来管理bit。

二、安装方法

  直接 pip install bitstring。

三、常用类

  bitstring模块有四个类,Bits、ConstBitStream、BitArray、BitStream,其中BitArray继承自Bits,而BitStream继承自ConstBitStream和BitArray,而ConstBitStream也是继承自Bits。

四、使用方法

  

1
2
3
4
from bitstring import BitArray, BitStream
 
= BitArray('0xff01')
= BitArray('0b110')

  

注意此处应传入字符串,若直接传入整型参数,则表示创建一个bit位数为该整型参数值的对象。

1
2
3
>>> s=BitArray(3)
>>> s
BitArray('0b000')

  

1
2
3
4
>>> type(a)
<class 'bitstring.BitArray'>
>>> type(b)
<class 'bitstring.BitArray'>

上述代码实例化了两个对象,a和b便可以调用BitArray的方法。

其他构造方法

1
2
3
4
5
6
7
8
9
10
# from a binary string
= BitArray('0b001')
# from a hexadecimal string
= BitArray('0xff470001')
# straight from a file
= BitArray(filename='somefile.ext')
# from an integer
= BitArray(int=540, length=11)
# using a format string
= BitArray('int:11=540')

  

进制转换

1
2
3
4
5
6
7
8
>>> a.bin
'1111111100000001'
>>> b.oct
'6'
>>> b.int
-2
>>> a.bytes
b'\xff\x01' 

注意,转换后的进制类型为字符串。

bit位增加与减少

此处的操作类似于字符串的叠加,注意+前后的变量顺序会影响结果。

1
2
3
4
>>> (b + [0]).hex
'c'
>>> ([0+ b).hex
'6'

  

1
2
3
4
5
6
>>> b+[0]*3
BitArray('0b110000')
>>> b+[1]*2
BitArray('0b11011')
>>> b+5
BitArray('0xc0')

此处可用BitArray([0])、BitArray('0b0')、BitArray(bin='0')、'0b0'等方式代替[0],或者直接用整型,比如5,此时代表操作5个bit为0的字符串进行叠加。

以列表/字符串的方法按字符串进行操作

1
2
3
4
5
>>> print(a[3:9])
0b111110
>>> del a[-6:]
>>> print(a)
0b1111111100 

 

1
2
3
>>> a.prepend('0b01')
>>> a.append('0o7')
>>> a += '0x06' 

以字符串的方式进行查找和替换

1
2
3
>>> a = BitArray('0xa9f')
>>> a.find('0x4f')
(3,) 

find方法返回所有符合条件的起始下标,此处的下标指的是bit的下标。

a按字符串进行拆分可以分成三个字符串的叠加。

1
2
>>> a == '0b101, 0x4f, 0b1'
True

  

1
2
3
4
5
>>> a=BitArray('0b110111100000110')
>>> a.replace('0b110','0b1')
3
>>> a.bin
'111100001' 

replace方法则是将符合条件的进行替换。

构造bitstring 

使用pack方法进行构建,传入格式和变量值,则会一一对应进行构造,注意此方法返回的是bitstream类型。

1
2
width, height = 352288
= bitstring.pack('0x000001b3, 2*uint:12', width, height)

其中‘2*uint:12’表示构造两个bit位为12的变量,对应的是width和height变量,‘0x000001b3’本身就是格式化后的变量值,因此不需要再传入变量。

除了上述方法,还可以将格式和变量值作为变量传入。

1
2
3
4
5
6
7
8
9
10
11
12
fmt = 'sequence_header_code,
uint:12=horizontal_size_value,
uint:12=vertical_size_value,
uint:4=aspect_ratio_information'
 
= {'sequence_header_code''0x000001b3',
'horizontal_size_value'352,
'vertical_size_value'288,
'aspect_ratio_information'1
}
 
= bitstring.pack(fmt, **d)

  

以上代码s的结果为BitStream('0x000001b31601201'),若构造的参数无法转换成十六进制,则会返回两个字符串。

 

1
2
3
4
5
6
7
8
9
10
11
12
fmt = 'sequence_header_code,
uint:11=horizontal_size_value,
uint:12=vertical_size_value,
uint:4=aspect_ratio_information'
 
= {'sequence_header_code''0x000001b3',
'horizontal_size_value'352,
'vertical_size_value'288,
'aspect_ratio_information'1
}
 
= bitstring.pack(fmt, **d)

  

以上代码s的结果为BitStream('0x000001b32c0240, 0b001')

除此之外还有另外一种构造方法。

1
2
3
4
5
6
7
8
format = 'hex:32=start_code, uint:12=width, uint:12=height'
 
# 方法一
= {'start_code''0x000001b3''width'352'height'288}
= bitstring.pack(format**d)
 
# 方法二
= bitstring.pack(format, width=352, height=288, start_code='0x000001b3')

  

解析BitStream

BitStream继承自BitArray,拥有BitArray的所有方法,同时又继承自ConstBitStream,因此多了解析方法。

BitStream可根据下标pos来进行索引和读取,默认从0开始。

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> s
BitStream('0x000001b31601201')
 
>>> s.pos
0
>>> s.read(24)
BitStream('0x000001')
>>> s.pos
24
>>> s.read('hex:8')
'b3'
>>> s.pos
32

  

read函数中直接填整型数字,则表示从pos位置开始切换该整型值,返回一个新的BitStream。

read函数还可以指定返回的类型,如s.read("hex:8"),表示从pos位置开始读取8个bit,并以十六进制的方式进行返回,返回的是字符串。

s.read("int:8"),表示从pos位置开始读取8个bit,并以十进制的方式进行返回,返回的是整型。

 

BitStream还能以列表的方式一次性返回多个解析值。

1
2
>>> s.readlist('2*uint:12')
[352288]

 

通过格式化的形式解析。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 十六进制数据消息
recv_data = "0200000002040000000C00000013093132372E302E302E31"
 
# 解析消息
bs = bitstring.BitStream(hex=recv_data)
 
fmt_head2 = """
       hex:32=id_hex,
       hex:8=valueLen_hex,
   """
res_list = bs.readlist(fmt_head2)
 
id_hex = res_list[0]
valueLen_hex = res_list[1]
valueLen = int(valueLen_hex, base=16)
 
fmt_head3 = """
       hex:valueLen_hex=value_hex,
   """
res_list = bs.readlist(fmt_head3, valueLen_hex=valueLen * 8)
value_hex = res_list[0]

  

 另外,BitStream提供了一种和readlist类似的方法unpack,可以按照一定的格式从头开始解析。

1
2
>>> s.unpack('bytes:4, 2*uint:12, uint:4')
['\x00\x00\x01\xb3'3522881]

 

若中间有x个bit位不需要解析时,可在fmt中使用pad:x来占位,则返回的解析列表不会包含pad占位的内容。 

readlist和unpack的区别在于readlist是根据s.pos值来确定解析的起始位置,而unpack则是每次都是从头开始解析。  

 大端模式与小端模式 

1
2
3
4
5
6
7
>>> big_endian = BitArray(uintbe=1, length=16)
>>> big_endian
BitArray('0x0001')
 
>>> little_endian = BitArray(uintle=1, length=16)
>>> little_endian
BitArray('0x0100')

  

 利用bitstring模块解析JT808报文

JT808消息结构

 

 

JT808消息头结构

 

 

JT808消息体结构

 

 

posted @ 2021-10-27 10:18  清清宝宝007  阅读(1490)  评论(0编辑  收藏  举报