字节交换
来源:Numpy官网:https://numpy.org/doc/stable/user/basics.html
文章目录
- 字节交换
- 导包
- 【1】字节排序和ndarrays 简介
- 【2】更改字节顺序
导包
import numpy as np
【1】字节排序和ndarrays 简介
ndarray 是一个对象,它为内存中的数据提供 python 数组接口。
通常,要使用数组查看的内存与运行 Python 的计算机的字节顺序不同。
例如,我可能正在使用具有小端 CPU 的计算机(例如英特尔奔腾),但我已从大端计算机写入的文件中加载了一些数据。假设我从 Sun(大端序)计算机写入的文件中加载了 4 个字节。我知道这 4 个字节代表两个 16 位整数。在大端计算机上,双字节整数首先存储最高有效字节 (MSB),然后存储最低有效字节 (LSB)。因此,字节按内存顺序为:
- MSB 整数 1
- LSB 整数 1
- MSB 整数 2
- LSB 整数 2
假设两个整数实际上是 1 和 770。由于 770 = 256 * 3 + 2,因此内存中的 4 个字节将分别包含:0、1、3、2。 我从文件加载的字节将包含以下内容:
big_end_buffer = bytearray([0, 1, 3, 2])
print(big_end_buffer)
bytearray(b'\x00\x01\x03\x02')
我们可能希望使用 ndarray 来访问这些整数。在这种情况下,我们可以围绕这个内存创建一个数组,并告诉 numpy 有两个整数,它们是 16 位和大端序:
big_end_arr = np.ndarray(shape=(2,), dtype='>i2', buffer=big_end_buffer)
print(big_end_arr)
[ 1 770]
big_end_arr[0]
1
big_end_arr[1]
770
请注意上面的 >i2 数组 dtype。>表示“大端序”(<是小端序),i2表示“有符号2字节整数”。例如,如果我们的数据表示单个无符号 4 字节小端整数,则 dtype 字符串将为 <u4.
little_end_u4 = np.ndarray(shape=(1,), dtype='<u4', buffer=big_end_buffer)
print(little_end_u4)
[33751296]
little_end_u4[0] == 1 * 256 ** 1 + 3 * 256 ** 2 + 2 * 256 ** 3
True
【妙啊】
【2】更改字节顺序
从介绍中可以想象,有两种方法可以影响数组的字节顺序与它正在查看的基础内存之间的关系:
-
更改数组 dtype 中的字节顺序信息,以便它将基础数据解释为采用不同的字节顺序。这是 arr.newbyteorder() 的作用
-
更改基础数据的字节顺序,使 dtype 解释保持原样。这就是arr.byteswap()所做的。
需要更改字节顺序的常见情况包括:
-
数据和 dtype 字节序不匹配,并且希望更改 dtype,使其与数据匹配。
-
数据和 dtype 字节序不匹配,并且希望交换数据以使它们与 dtype 匹配
-
数据和 dtype 字节序匹配,但希望交换数据并且 dtype 反映这一点
① 数据与dtype字节序不匹配,更改dtype以匹配数据
先来一些错误的数据
wrong_end_dtype_arr = np.ndarray(shape=(2,), dtype='<i2', buffer=big_end_buffer)
print(wrong_end_dtype_arr)
[256 515]
wrong_end_dtype_arr[0]
256
这种情况的明显解决方法是更改 dtype,以便它给出正确的字节序:
fixed_end_dtype_arr = wrong_end_dtype_arr.newbyteorder()
print(fixed_end_dtype_arr)
[ 1 770]
fixed_end_dtype_arr[0]
1
注意,数组在内存中没有更改:
fixed_end_dtype_arr.tobytes() == big_end_buffer
True
② 数据和类型字节序不匹配,更改数据以匹配 dtype
如果需要按特定顺序排列内存中的数据,则可能需要执行此操作。例如,我们可能要将内存写出到需要特定字节排序的文件中。
fixed_end_mem_arr = wrong_end_dtype_arr.byteswap()
fixed_end_mem_arr[0]
1
现在数组在内存中发生了变化:
fixed_end_mem_arr.tobytes() == big_end_buffer
False
③ 数据和 dtype 字节序匹配、交换数据和 dtype
您可能具有正确指定的数组 dtype,但您需要该数组在内存中具有相反的字节顺序,并且您希望 dtype 匹配,以便数组值有意义。在这种情况下,您只需执行前面的两个操作:
swapped_end_arr = big_end_arr.byteswap().newbyteorder()
swapped_end_arr[0]
1
swapped_end_arr.tobytes() == big_end_buffer
False
使用 ndarray astype 方法可以实现将数据转换为特定 dtype 和字节排序的更简单方法:
swapped_end_arr = big_end_arr.astype('<i2')
swapped_end_arr[0]
1
swapped_end_arr.tobytes() == big_end_buffer
False