Python二进制数据处理
目录
- 前言
- str与bytes
- base64模块
- struct模块
- 参考链接
前言
本文所涉及到的代码均基于python 3.x。
str与bytes
在写代码时,我们经常会涉及到字符串的处理,但字符串的编码问题常常令我们很头痛。当然本篇文章不是去说编码的,而是主要讲讲二进制处理,python 3为我们提供了bytes,利用bytes可以一定程度上缓解编码出错的问题,因为bytes是字节序列,无所谓编码。下面先看一个例子。
_str = 'str'
print(type(_str))
# 输出为 <class 'str'>_bytes = b'bytes'
print(type(_bytes))
# 输出为<class 'bytes'>
看到差别了吧,在定义字符串的时候,字符串引号之前加上一个b
那么所定义的就是bytes。
上面的_bytes变量虽然是字节序列,但是print()
出来只不过字符串前面加了个b
,好像和str没有多大区别,那么我们再看下面这段代码:
_str = '中国'
print(_str)
# 中国_bytes = '中国'.encode()
print(_bytes)
# b'\xe4\xb8\xad\xe5\x9b\xbd'
这下差别就比较明显了吧,对于中文,str打印出来是它本身,bytes打印出来就是它的16进制编码了。当你在网络上发送一个中文str给别人的时候,如果你使用的编码格式和对方不一致,对方直接读取str可能就是乱码,而bytes就没有这个问题。
上面的代码还涉及到str和bytes的转换,这里我们也说一下。先看代码:
_str = '中国'
print(type(_str)) # <class 'str'>
print(_str) # 中国_bytes = _str.encode()
print(type(_bytes)) # <class 'bytes'>
print(_bytes) # b'\xe4\xb8\xad\xe5\x9b\xbd'new_str = _bytes.decode()
print(type(new_str)) # <class 'str'>
print(new_str) # 中国
可以看到,str转bytes通过encode()方法,而bytes转str则通过decode()方法,encode()方法默认encoding=‘utf-8’。
另外,str有的方法,bytes大部分也都有,因为这篇文章不是主要讲字符串处理问题的,所以这里就不展开了。
base64模块
现在我们来说一下base64模块。首先,base64是一种用64个字符来表示二进制数据的方法。具体表示方法是:
首先定义出用来表示二进制数据的64个字符:
['a', 'b', ..., '+', '/'] # 省略中间60个字符
然后,将需要处理的二进制数据进行分组,每3个字节一组,也就是3 x 8 = 24 bit
。然后再将这24个bit划分为4组,每组6个bit。那么每组的6个bit就可以表示0至63之间的数字,这样我们就可以查一开始定义的64个字符表,来获得二进制数据的字符表示了。
这种情况下,原始二进制数据的长度就增加了,那岂不是增大了数据传输的压力?这里,需要清楚的一点是,base64处理的主要是显示乱码问题。如果我们直接打开一些二进制文件,很多情况下出来的是一堆乱码,而用base64表示之后,我们打开这些数据,就能够清楚的看到里面的内容,比如邮件、图片等,当然它也用于URL、Cookie、网页中传输少量数据。
还有一个问题,如果原始二进制数据的字节数不是3的整数倍怎么办?在这种情况下,base64会在原始二进制数据末尾添加\x00
来补齐数据,然后,在编码后的字符串,这些被补齐的地方表示成=
,在解码的时候,这些=
再被去掉,也能得到正确的原始二进制数据。这些操作在python的base64模块自动完成的,我们实际不用关心。
说了这么多,我们看一下python里怎么使用base64吧。
import base64_bytes = b'test bytes'b64 = base64.b64encode(_bytes)
print(b64) # b'dGVzdCBieXRlcw=='new_bytes = base64.b64decode(b64)
print(new_bytes) # b'test bytes'
注意,上面的b'test bytes'
是10个字节,经过base64处理后末尾添加了两个=
,这样就是12个字节,也就是3的整数倍。
最后,前面有说到过,base64可以用来处理URL,但base64的64个字符里会有+
/
,这些符号在URL中是不能直接作为参数的。因此, base64还提供了一种url safe的处理方式,也就是把base64编码后的字符串中的+
/
替换成-
_
。下面看一个例子:
import base64_bytes = b'\xfd\xcf\xbe'
b64 = base64.b64encode(_bytes)
print(b64) # b'/c++'us_b64 = base64.urlsafe_b64encode(_bytes)
print(us_b64) # b'_c--'new_bytes = base64.urlsafe_b64decode(us_b64)
print(new_bytes) # b'\xfd\xcf\xbe'
可以看到,经过urlsafe_b64encode()编码的字符串相比b64encode()编码的字符串确实有所不同。
另外,base64的64个字符的顺序是可以自定义的,这样就可以自定义编码,但一般情况下没有这个必要。
struct模块
最后,我们来说一下struct模块,这也是python中常用的处理二进制数据的模块。
struct模块用来处理的是python数据和表示成python bytes对象的C结构体(struct)之间的转换,应用场景一般是处理文件和网络传输中的二进制数据。
我们还是通过一个例子来了解struct模块的应用吧:
struct s_data {unsigned short id;unsigned int length;char[5] data;
}
假设我们有一个上面这样的C结构体,那么它与python值之间如何转换呢?请看代码:
from struct import Structp_id = 0
p_length = 5
p_data = b'hello'c_struct = Struct('>HI5s')
packed = c_struct.pack(p_id, p_length, p_data)
print(packed) # b'\x00\x00\x00\x00\x00\x05hello'unpacked = c_struct.unpack(b'\x00\x00\x00\x00\x00\x05hello')
print(unpacked) # (0, 5, b'hello')
在上面的代码中,首先我们在python里定义了结构体里的各个成员,然后调用pack()方法把它打包成bytes,这样就可以与C进行数据交换了。又或者下面两行代码里,我们从C收到一串二进制数据,我们可以调用unpack方法把它解析出来(解析出来的数据是放在元组里的)。
在下面这行代码中我们实际定义了C结构体里的数据格式:
c_struct = Struct('>HI5s')
第一个符号>
表示数据采用大端方式(big-endian)存储,这个主要是考虑到有的C/C++的编译器使用了字节对齐。这个字符其实是定义了字节序、大小和打包后数据的对齐方式,可以参看下表:
Character | Byte Order | Size | Alignment |
---|---|---|---|
@ | native | native | native |
= | native | standard | none |
< | little-endian | standard | none |
> | big-endian | standard | none |
! | network(=big-endian) | standard | none |
如果我们在写程序的时候没有把第一个字符定义为上述表格中的字符,那么默认的是@
。需要注意的是,当我们想要处理与平台无关的数据格式时,使用size为standard的方式,不要使用native的方式。
>
符号后面的几个符号中,H
表示C里的unsigned short,I
表示C里的unsigned int,s
表示C里的char[],5s
表示的是5个元素的char数组。下面将C与python的对应类型列出来:
Format | C Type | Python Type | Standard size |
---|---|---|---|
x | pad byte | no value | |
c | char | bytes of length 1 | 1 |
b | signed char | integer | 1 |
B | unsigned char | integer | 1 |
? | _Bool | bool | 1 |
h | short | integer | 2 |
H | unsigned short | integer | 2 |
i | int | integer | 4 |
I | unsigned int | integer | 4 |
l | long | integer | 4 |
L | unsigned long | integer | 4 |
q | long long | integer | 8 |
Q | unsigned long long | integer | 8 |
n | ssize_t | integer | |
N | size_t | integer | |
e | float | 2 | |
f | float | float | 4 |
d | double | float | 8 |
s | char[] | bytes | |
p | char[] | bytes | |
P | void* | integer |
需要注意的是,Standard size列有固定值的都是与平台无关的大小,而没有具体的值的,是与平台相关的。
最后,对于上面的代码,其实还可以这样写:
import structp_id = 0
p_length = 5
p_data = b'hello'packed = struct.pack('>HI5s', p_id, p_length, p_data)
print(packed) # b'\x00\x00\x00\x00\x00\x05hello'unpacked = struct.unpack('>HI5s', b'\x00\x00\x00\x00\x00\x05hello')
print(unpacked) # (0, 5, b'hello')
但是我觉得这种写法没有实例方法优雅,特别是在代码中同样的结构出现在多个地方的时候。通过创建一个Struct
实例,格式化字符串只会指定一次并且所有的操作被集中处理。这样一来代码维护就变得简单了(因为只需要改变一处代码即可)。
参考链接
廖雪峰 base64 教程
廖雪峰 struct 教程
python3 module struct doc
Python二进制数据处理相关推荐
- python基础代码库-Python基础数据处理库-NumPy
最近更新:2017-07-19 NumPy是Python做数据处理的底层库,是高性能科学计算和数据分析的基础,比如著名的Python机器学习库SKlearn就需要NumPy的支持.掌握NumPy的基础 ...
- Python空间数据处理环境搭
Python空间数据处理环境搭 Conda的下载和安装 什么是Conda? 官方定义:Package, dependency and environment management for any la ...
- Python爬虫-数据处理与存储
Python爬虫-数据处理与存储 数据处理 可以使用pandas模块来实现数据处理,pandas是一个开源的并且通过BSD许可的库.它主要为Python语言提供高性能.易于使用数据结构和数据分析工 ...
- Javascript中二进制数据处理方法
Javascript中二进制数据处理方法 转载于:https://www.cnblogs.com/motadou/archive/2012/02/19/2358514.html
- python 二进制,十进制,十六进制
十进制:decimal system,每一位最高为9,达不到10 二进制:binary system,每一位最高为1,达不到2 八进制:octonary number system,每一位最高为7,达 ...
- Power BI Power Query页面使用python进行数据处理
1.对Power Query的表格调用python进行数据处理.如图所示进入python编辑界面. 2.右边的操作列表中会多出python脚本的操作步骤. 在中间的窗口中编写python脚本,Powe ...
- Python大数据处理库 PySpark实战 总结四
Python大数据处理库 PySpark实战四 ETL 实战 实验数据来源 数据加载 观察资料 选择.筛选与聚合 机器学习实战 实验数据来源 数据加载 统计描述 清洗与变形 Pipeline 逻辑回归 ...
- Python读写矢量数据(2)矢量数据写入(属性数据)——Python地理数据处理学习分享
这一节主要介绍矢量数据的写入(只有属性数据,无几何),如果有读者没有读取的基础建议先看一下上一篇文章,需要对矢量数据读取有一定的了解才能继续学习本节.在这里我们用到的数据仍为goble文件夹下的数据, ...
- python十进制转换其他进制直到输入q结束,python二进制转换,python将十进制转为二进制,题目描述:输入一个整...
python二进制转换,python将十进制转为二进制,题目描述:输入一个整 题目描述: 输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示. 分析: python没有unsignedin ...
最新文章
- 人脸识别争议再起 实际应用利弊几何?
- 使用VGG训练Imagenet
- 爬虫python需要什么软件-学python爬虫能做什么
- Java 子类 instanceof 父类
- 递归思想完成n皇后问题
- 【MATLAB】求点到多边形的最短距离
- 2016版excel_憋了三年,整理出这些相见恨晚的Excel大神技巧,分分钟做出超赞Excel表格!...
- php 小程序页面传参,介绍小程序中传递参数的实现方法
- sql 字段相减_R语言ETL系列:创建字段(mutate)
- [转]抛弃jQuery,使用原生JavaScript
- 射手科技公开课第一辑 『项目管理和代码规范』
- 妙用next数组打表求最小循环节len
- ★大脑的9大未解之谜
- MyCat重要概念以及基础配置详解
- 记录学习算法心得(时间复杂度和空间复杂度)
- 成都市中小学计算机创客,我校荣获2019四川省中小学电脑制作活动机器人暨创客竞赛团体一等奖...
- 星座运势预测,python爬虫
- Golang - bufio 包
- .net出现80080005错误的解决办法
- Android仿手机QQ空间动态评论,自动定位到输入框
热门文章
- 基于微信小程序的校园食堂窗口自助点餐系统#毕业设计
- 点击化学(Click chemistry) 叠氮-PEG4-NHS/Biotin-PEG-N3/Azid/DBCO-EPG-NHS/DBCO-NH2
- Microsoft Office word 2019教程 - word中的excel表格随着excel表格的变化而变化
- 雪球产品,场外雪球结构介绍
- ps aux 进程状态为 I (大写i)
- Java 阿里云图片添加水印
- 如何规避海外置业风险,2019必备海外房产投资技巧
- 编程高效学习方法(费曼学习法)
- chatgpt智能提效职场办公-ppt怎么转pdf文件
- android连不上电脑,安卓手机USB数据线连接不上电脑的最佳解决方法