- python字节串与int、float、string互转,字节串与元组、列表、字符串互转
- ❤初识python字节串
- ❤格式字符串(format)
- 字节顺序,大小和对齐方式
- 格式字符
- ❤字节串与int、float互转
- ❤字节串与列表、字符串互转
- 1. 元组或列表数据与字节串互转(方案一)
- 2. 元组或列表数据与字节串互转(方案二)
- 3. 字符串与字节串互转
python字节串与int、float、string互转,字节串与元组、列表、字符串互转
bytes 对象是由单个字节构成的不可变序列。 由于许多主要二进制协议都基于 ASCII 文本编码,因此 bytes 对象提供了一些仅在处理 ASCII 兼容数据时可用,并且在许多特性上与字符串对象紧密相关的方法。
本文主要介绍了字节串与python基本数据类型之间的相互转换。
❤初识python字节串
虽然 bytes 字面值和表示法是基于 ASCII 文本的,但 bytes 对象的行为实际上更像是不可变的整数序列,序列中的每个值的大小被限制为
my_bytes = b'\x03\x04\x05\x06\x07'
print(type(my_bytes))
print(my_bytes)
# 结果:
<class 'bytes'>
b'\x03\x04\x05\x06\x07'
除了字面值形式,bytes 对象还可以通过其他几种方式来创建:
- 指定长度的以零值填充的 bytes 对象: bytes(10)
my_bytes = bytes(10)
print(my_bytes)
# 结果:
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
- 通过由整数组成的可迭代对象: bytes([3,4,5,6,7]),特别注意序列中的每个值的大小被限制为
a = [3,4,5,6,7] # 特别注意值不能大于256
my_bytes = bytes(a)
print(my_bytes)
# 结果:
b'\x03\x04\x05\x06\x07'
当序列值不满足 时报错:ValueError: bytes must be in range(0, 256)
- 通过缓冲区协议复制现有的二进制数据: bytes(obj)
❤格式字符串(format)
字节串的转换需要一个非常重要的参数format,因为存储的bytes字节串是无脑的二进制存储或字节存储,不知道你存的是什么格式的数据,也不知道你存了多少个数据,所以就需要格式字符串(format)来表示。
如果你拿到一个字节串数据,不知道它的数据类型的话就白搞,赶紧看看自己是不是还有什么信息没获取到。
格式字符串是用来在打包和解包数据时指定预期数据格式的说明。 在转换过程中使用指定被打包/解包数据类型的格式字符进行构建。 此外,还有一些特殊字符用来控制字节顺序,大小和对齐方式。
字节顺序,大小和对齐方式
默认情况下,C类型以机器的本机格式和字节顺序表示,并在必要时通过跳过填充字节进行正确对齐(根据C编译器使用的规则)。 也就是说你数据是这台机器产生的,在这台机器使用就不用关心这些。
或者,根据下表,格式字符串的第一个字符可用于指示打包数据的字节顺序,大小和对齐方式:
字符 | 字节顺序 | 大小 | 对齐方式 |
@ | 按原字节 | 按原字节 | 按原字节 |
= | 按原字节 | 标准 | 无 |
< | 小端 | 标准 | 无 |
> | 大端 | 标准 | 无 |
! | 网络(=大端) | 标准 | 无 |
注意:
- 如果第一个字符不是其中之一,则假定为 ‘@’ 。
- 本机字节顺序可能为大端或是小端,取决于主机系统的不同。 例如, Intel x86 和 AMD64 (x86-64) 是小端的; Motorola 68000 和 PowerPC G5 是大端的; ARM 和 Intel Itanium 具有可切换的字节顺序(双端)。 请使用
- 本机大小和对齐方式是使用 C 编译器的 sizeof 表达式来确定的。 这总是会与本机字节顺序相绑定。
- 标准大小仅取决于格式字符;请参阅 格式字符 部分中的表格。
- 请注意 ‘@’ 和 ‘=’ 之间的区别:两个都使用本机字节顺序,但后者的大小和对齐方式是标准化的。
- 格式 ‘!’ 适合给那些宣称他们记不得网络字节顺序是大端还是小端的可怜人使用。
- 没有什么方式能指定非本机字节顺序(强制字节对调);请正确选择使用 ‘<’ 或 ‘>’。
格式字符
格式字符具有以下含义:
- C 和 Python 值之间的按其指定类型的转换应当是相当明显的。
- ‘标准大小’列是指当使用标准大小时以字节表示的已打包值大小; 也就是当格式字符串以 ‘<’, ‘>’, ‘!’ 或 ‘=’ 之一开头的情况。
- 当使用本机大小时,已打包值的大小取决于具体的平台。
格式 | C 类型 | Python 类型 | 标准大小 |
x | 填充字节 | 无 | |
c | char | 长度为 1 的字节串 | 1 |
b | signed char | 整数 | 1 |
B | unsigned char | 整数 | 1 |
? | _Bool | bool | 1 |
h | short | 整数 | 2 |
H | unsigned short | 整数 | 2 |
i | int | 整数 | 4 |
I | unsigned int | 整数 | 4 |
l | long | 整数 | 4 |
L | unsigned long | 整数 | 4 |
q | long long | 整数 | 8 |
Q | unsigned long | ||
long | 整数 | 8 | |
n | ssize_t | 整数 | (3) |
N | size_t | 整数 | (3) |
e | (6) | 浮点数 | 2 |
f | float | 浮点数 | 4 |
d | double | 浮点数 | 8 |
s | char[] | 字节串 | |
p | char[] | 字节串 | |
P | void * | 整数 | (5) |
格式字符之前可以带有整数重复计数。 例如,格式字符串 ‘4h’ 的含义与 ‘hhhh’ 完全相同。
格式之间的空白字符会被忽略;但是计数及其格式字符中不可有空白字符。
❤字节串与int、float互转
有了上面的基础后,下面就可以开始愉快的转换了。这里我们只拿int类型和float类型的数据举个例子,其他数据类型的都差不多,相信聪明如你一定能搞定!❤❤❤❤
- 字节串与int类型数据互转:
import struct
# bytes转int:
a = int(-300)
my_bytes = struct.pack('i',a) # 这里的i对于的是int数据类型的格式字符,参见上面。
print(my_bytes)
# int转bytes:
my_data = struct.unpack('i',my_bytes)[0] # 返回的是元组数据,所以取了第一个值。
print(my_data)
# 输出结果:
b'\xd4\xfe\xff\xff'
-300
- 字节串与float类型数据互转:
import struct
# float转bytes:
a = float(-30.9)
my_bytes = struct.pack('f',a)
print(my_bytes)
# bytes转float:
my_data = struct.unpack('f',my_bytes)[0]
print(my_data)
# 输出结果:
b'33\xf7\xc1'
-30.899999618530273
这里反转换结果误差来自计算机存储浮点数据时产生的误差。
❤字节串与列表、字符串互转
1. 元组或列表数据与字节串互转(方案一)
import struct
from ctypes import create_string_buffer
my_data = [300,400,-500,-600] # 你给的数据
my_format = 'i' # 列表里面数据的类型
my_format_size = 4 # 该类型对应的长度
# 元组或列表数据转字节串:
my_buffer = create_string_buffer(my_format_size*len(my_data))
for i in range(len(my_data)):
struct.pack_into(my_format,my_buffer,my_format_size*i,my_data[i])
print(my_buffer.raw)
# 字节串转回元组或列表:
my_bytes = my_buffer.raw # 你给的数据,这里取得上面生成的
my_format = 'i' # 跟上面一样
my_format_size = 4 # 跟上面一样
data = []
for i in range(int(len(my_bytes)/my_format_size)):
tmp = struct.unpack_from(my_format,my_bytes,i*my_format_size)
data.append(tmp[0])
print(data)
输出结果:
b',\x01\x00\x00\x90\x01\x00\x00\x0c\xfe\xff\xff\xa8\xfd\xff\xff'
[300, 400, -500, -600]
2. 元组或列表数据与字节串互转(方案二)
import struct
from ctypes import create_string_buffer
my_data = [300,400,-500,-600] # 你给的数据
my_format = 'i' # 列表里面数据的类型
my_format_size = 4 # 该类型对应的长度
# 元组或列表数据转字节串:
my_bytes = bytes()
for i in range(len(my_data)):
my_bytes = my_bytes + struct.pack(my_format,my_data[i])
print(my_bytes)
# 字节串转回元组或列表:
my_bytes = my_buffer.raw # 你给的数据,这里取得上面生成的
my_format = 'i' # 跟上面一样
my_format_size = 4 # 跟上面一样
data = []
tmp = struct.unpack(str(int(len(my_bytes)/my_format_size)) + my_format,my_bytes)
print(list(tmp))
输出结果:
b',\x01\x00\x00\x90\x01\x00\x00\x0c\xfe\xff\xff\xa8\xfd\xff\xff'
[300, 400, -500, -600]
3. 字符串与字节串互转
因为字节串的本质就是字符串,所以两者本质就是一样的。
# 字符串数据转字节串:
my_string = "i am caiji"
my_bytes = my_string.encode()
print(my_bytes)
print(type(my_bytes))
# 字节串转字符串数据:
my_data = my_bytes.decode()
print(my_data)
print(type(my_data))
输出结果:
b'i am caiji'
<class 'bytes'>
i am caiji
<class 'str'>