常见的数据类型转换

Posted by FanHao on 2020-05-15

以下代码均在python3.6下验证通过;

因工作需要,使用scapy解析和构造网络数据包时,需要对解包后得到的字节流数据进行处理,同时需要处理数据转换,以下作为一个记录总结。

一、进制转换

1
2
3
4
5
6
7
8
9
10
11
# 10进制转换成16进制
>>> hex(16)
'0x10'
>>> hex(11)
'0xa'
# 10进制转换成8进制
>>> oct(8)
'0o10'
# 10进制转换成2进制
>>> bin(4)
'0b100'

二、字符串与整数

字符转整数

10进制整数与字符串

1
2
3
4
# 转换成10进制整数,默认参数为10
>>> int('12')
12
>>> int('20',base=10)

16进制整数与字符串

1
2
3
4
5
6
7
8
9
# 字符串转换成16进制整数
>>> int('12',16)
18
>>> int('10',16)
16
>>> int('0x11',16)
17
>>> int('0x2a',16)
42

8进制整数与字符串

1
2
3
4
>>> int('10',8)
8
>>> int('012',8)
8

2进制整数与字符串

1
2
3
4
5
# 字符串转成2进制整数
>>> int('11',2)
3
>>> int('111',2)
7

字符串也可转换成任意进制整数,但要注意字符串中的数字不能超出进制数。

1
2
3
4
5
6
7
# 如下字符串35转换为4进制的整数,将会报错。因为字符串中的5比4大。
>>> int('35',4)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 4: '35'
>>> int('13',4)
7
整数转字符

利用以下两个方法可实现ASCII值与字符的相互转换。更多字符与值对应关系可以去查ASCII码表。

1
2
3
4
5
6
7
8
# ASCII码10进制值为65的字符是'A'
>>> chr(65)
'A'
# 'a'的ASCII码10进制值为97
>>> ord('a')
# 换行符 ASCII码值
>>> ord('\n')
10
应用实例

mac地址转整数。

1
2
3
a = 'FF:FF:FF:FF:FF:FF'.split(:)
for i in a:
int(i,16)

三、bytes数据

创建bytes数据

python3中,字符串与bytes类型是两种不同类型的数据。字符串以字符为单位进行处理,bytes类型以字节为单位进行处理。

1
2
3
4
5
6
7
8
9
10
11
# 创建一个空的bytes
>>> b = b''
>>> b = bytes()
# 指定bytes类型的数据
>>> b = b'hello'
b'hello'
# 利用bytes方法将字符串转换成bytes数据
>>> b = bytes('test',encoding='utf-8')
b'test'
>>> 'test'.encode()
b'test'
byte字节和string转换
1
2
3
4
5
6
7
8
# 字符串编码成bytes字节流
>>> msg = '我要成为code的魔法师'
>>> msg.encode()
b'\xe6\x88\x91\xe8\xa6\x81\xe6\x88\x90\xe4\xb8\xbacode\xe7\x9a\x84\xe9\xad\x94\xe6\xb3\x95\xe5\xb8\x88'
# bytes字节通过decode解码为string格式
>>> msg_bytes = msg.encode()
>>> msg_bytes.decode()
'我要成为code的魔法师'
将bytes数据转换成string
1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> msg_b = b'\xe9\xad\x94\xe6\xb3\x95\xe5\xb8\x88'
# 方法一
>>> string(msg_b,'utf-8')
'魔法师'
# 方法二,参数默认utf-8,第二参数strict
>>> msg_b.decode()
'魔法师'
# 方法三,忽略非法字符
>>> msg_b1 = b'\xe9\xad\x94\xe6\xb3\x95\xe5\xb8\x88\x90'
>>> msg_b1.decode('utf-8','ignore')
'魔法师'
# 方法四,用?取代非法字符
>>> msg_b1.decode('utf-8','replace')
'魔法师�'
操作bytes数据

与操作字符串数据类似,可对bytes数据进行分片,replace方法。

1
2
3
4
5
6
7
>>> msg_b = b'\xe9\xad\x94\xe6\xb3\x95\xe5\xb8\x88'
>>> msg_b[2:]
b'\x94\xe6\xb3\x95\xe5\xb8\x88'
>>> msg_b[-2:]
b'\xb8\x88'
>>> msg_b.replace(b'\xb8\x88',b'\xb3\xb95')
b'\xe9\xad\x94\xe6\xb3\x95\xe5\xb3\xb95'

四、应用实例

实例一

将list中的字符串转成bytes类型数据,如’FF’转换成’\xff’。参考stackoverflow上的回答。

1
2
3
4
# 方法一,本方法比方法二处理速度更快
import binascii
data = ['FF','FF','FF','FF']
bytestring = binascii.unhexlify(''.join(data))
1
2
# 以上代码 bytestring结果如下
b'\xff\xff\xff\xff'
1
2
3
4
5
# 方法二
data = ['FF','FF','FF','FF']
bytesstring = bytes(int(x,16) for x in data)
# 以上代码 bytestring结果如下
b'\xff\xff\xff\xff'

实例二

1
2
3
4
5
6
7
8
9
10
11
12
# 将ip地址转换成数据报文中bytes数据
# ip='192.168.0.120'
import binascii
def ip2bytes(ip):
b = []
ip_num_list = ip.split('.')
for num in ip_num_list:
b.append(hex(int(num))).replace('0x','')
for i in range(len(b)):
if len(b[i])<2:
b[i] = '0' + b[i]
return binascii.unhexlify(''.join(b))