Python使用base64模块进行二进制数据编码详解
作者:GanZiQim 发布时间:2023-08-26 20:13:13
前言
昨天团队的学妹来问关于POP3协议的问题,所以今天稍稍研究了下POP3协议的格式和Python里面的poplib。而POP服务器往回传的数据里有一部分需要用到Base64进行解码,所以就顺便看了下Python里面的base64模块。
本篇先讲一下base64模块,该模块提供了关于Base16,Base32,Base64,Base85和Ascii85的编码和解码相关的函数。有关poplib模块的内容,会在后面发上来。嗯,又挖了一个坑,这辈子挖的坑填不完了...
以下内容摘自http://bbs.chinaunix.net/thread-1150250-1-1.html,详细说明了为什么回传的数据会先经过Base64编码:
由於歷史原因,Internet上有些郵件系統只支援7Bit的字元傳輸,而漢字的內碼是8Bit的,當在電子郵件中發送中文時,如果經過這些只支援7Bit字元的郵件系統,便會將漢字內碼的第八位元的1全部變成0。
以”中文”兩字為例,HEX為A4A4A4E5,當最高位元被清掉時就會變成24242465,也就是”$$$e”。telnet也存在這樣子的問題。
除了中文郵件外,使用電子郵件傳送圖片、程式、壓縮文件等也會發生這個問題。所以在電子郵件中一般採用各種郵件編碼方式來解決這個問題,將8Bit按照一定的規則進行編碼,便可以完好地通過只支持7Bit字元的郵件系統。
常見的郵件編碼有UU與MIME,而MIME(Multipurpose Internet Mail Extentions)一般翻譯成「多媒體傳送模式」,顧名思義,它標榜的就是可以傳送多媒體型式的檔案,可以在一封mail中附加各種型式檔案一起送出。
MIME定義兩種編碼方法:Base64與QP(Quote-Printable),兩者使用時機不同,QP的規則是對於資料中的7bits無須重複encode,僅8bits資料轉成7bits。QP編碼適用於非US-ASCII的文字內容,例如我們的中文檔案,而Base64的編碼規則,是將整個檔案重新編碼,編成7bits,它是用於傳送binary檔案時使用。由於編碼的方式不同,會影響編碼之後的檔案大小。有些較懶惰的軟體便都一律採用Base64編碼了。
Base64
base64模块提供了6个函数用于Base64的编码和解码,可以将他们分为三组。
base64.b64encode(s, altchars=None)
base64.b64decode(s, altchars=None, validate=False)
参数s代表需要编码/解码的数据。其中b64encode的参数s的类型必须是字节包(bytes)。b64decode的参数s可以是字节包(bytes),也可以是字符串(str)。
由于Base64编码后的数据中可能会含有'+'或者'/'两个符号,如果编码后的数据用于url或者文件系统的路径中,就可能会导致Bug。所以base64模块提供了将编码后的数据中'+'和'/'进行替换的方法。
参数altchars必须是长度为2的字节包,这两个符号会用于替换编码后数据中的'+'和'/'。这个参数默认是None。
参数validate默认为False。如果它为True时,base64模块在进行解码前会先检查s中是否有非base64字母表中的字符,如果有的话则抛出错误binascii.Error: Non-base64 digit found。
如果数据的长度不正确则会抛出错误binascii.Error: Incorrect padding。
>>> import base64
>>> x = base64.b64encode(b'test')
>>> x
b'dGVzdA=='
>>> base64.b64decode(x)
b'test'
base64.standard_b64encode(s)
base64.standard_b64decode(s)
这组函数会直接将参数s传到上一组函数中。
base64.urlsafe_b64encode(s)
base64.urlsafe_b64decode(s)
这组函数同样基于第一组函数,但进行编码后会将输出数据中的'+'和'/'替换为'-‘和'_'。解码前则将数据中的'-‘和'_'替换为'+'和'/'。
另,Base64编码还会产生一个符号'=',这个符号用于将数据长度填充到4的倍数。
Base32
base64.b32encode(s)
base64.b32decode(s, casefold=False, map01=None)
参数s与Base64一致。
Base32编码后的字符范围为[2-7A-Z],是不支持小写字母的。不过当参数casefold为True时,Base32解码时可以接受小写字母的输入。但是为了安全考虑,这个参数默认为False。
Base32的解码同时还允许将数字0替换为大写字母O,把数字1替换为大写字母I或者L。参数map01可以指定将数字1替换为哪个字符(源码中并没有限定必须是字母I或者L其中之一),当这个参数非None时,数字0总是会被替换为字母O。同样为了安全考虑,这个参数默认为None。
Base16
base64.b16encode(s)
base64.b16decode(s, casefold=False)
Base16编码后的字符范围为[0-9A-F]。
参数s和casefold的作用与Base32一致。
Base85
base64.b85encode(b, pad=False)
base64.b85decode(b)
参数b为用于编码/解码的数据,类型要求跟Base64的参数s一致。
参数pad为True时,在编码前会用b'\0'将数据填充到长度为4的倍数。不过在解码的时候不会移除这些填充数据。
这组函数是在Python3.4之后新增的。
Ascii85
base64.a85encode(b, *, foldspaces=False, wrapcol=0, pad=False, adobe=False)
参数b为用于编码的数据,类型必须为bytes。
参数foldspaces为True时会用b'y'来表示4个连续的空格。
参数wrapcol为一个整数,当wrapcol非0时,这个整数控制编码后的输出每多少个字符添加一个换行符b'\n'。
参数pad为True时,数据在编码前会用b'\0'填充到长度为4的倍数。解码的时候不会移除这些填充数据。
参数adobe指定了数据是否采用Adobe的格式。Adobe Ascii85的编码数据由<\~和\~>包围起来,如果这个参数为True,返回的数据会加上这对符号。
base64.a85decode(b, *, foldspaces=False, adobe=False, ignorechars=b' \t\n\r\v')
参数b为用于编码的数据,类型可以为bytes或者str。
参数foldspaces为True时会用b'y'来表示4个连续的空格。
参数adobe指定了数据是否采用Adobe的格式。Adobe Ascii85的编码数据由<\~和\~>包围起来,如果这个参数为True,解码前base64会先去掉这对符号。
参数ignorechars指定了解码时需要忽略掉的字符。默认包含了ASCII中所有的空白符。
这组函数是在Python3.4之后新增的。
base64模块的官方文档中提到:Base85和Ascii85使用5个字符编码4个字节,而Base64使用6个字符编码4个字节(实际上是4个字符编码3个字节),当空间不充裕时前两者会比Base64更高效。
旧API
base64仍然保留了一部分旧的API,用于一些特殊用途。
base64.encode(input, output)
base64.decode(input, output)
这组函数使用二进制文件作为数据源,并将编码/解码后的数据写入二进制文件。
base64.encodebytes(s)
base64.decodebytes(s)
encodebytes和b64encode在内部都是调用的binascii模块的b2a_base64,只不过encodebytes调用b2a_base64时newline参数使用默认值True。也就是说,encodebytes在输出数据的时候,每76个字节会添加一个换行符b'\n'。
decodebytes和默认参数下的b64decode基本一致。只有参数类型的检查不一样,decodebytes只支持bytes类型的数据。
base64.encodestring(s)
base64.decodestring(s)
这组函数在Python3.1之后就废弃了,目前会直接调用上一组函数。
总结
base64模块提供了对二进制数据进行编码的接口,其中包括了标准的Base64,Base32,Base16和事实标准Ascii85和Base85。通过学习这个模块,顺便学习了一下二进制数据编码的各种细节,感受颇深。有时候我们自以为了解计算机,了解互联网,其实每个人看到的都只是沧海一粟,不值一提。这个领域对于我来说还有很多未知,是等待探索的,而我也不会停止探索的脚步。
来源:http://blog.csdn.net/jy692405180/article/details/73272066
猜你喜欢
- 设计思路本文整理归纳以往的工作中用到的东西,现汇总成基础测试框架提供分享。框架采用python3 + selenium3 + PO + ya
- 为了组织search线的设计师交流会,特地去准备了一些资料。《SERP 2010》是其中一个,但是由于时间关系没有进行讨论。原著是英文报告,
- 网页广告 Banner 设计图文手册:采用以下要点来改善你的BANNER。广告并不便宜。 确信你的广告被第一时间读到。使用像这样的Sans
- matlab中的filter函数:y = filter(b,a,x)python实现matlab中的filter函数def filter_m
- 今天有人问起,晚上试着写出来,供参考; 以下代码兼容主流浏览器IE6、IE7、Firefox、Opera。从最简单的开始…………一
- 我开发了一个程序,数据在服务器端处理,通过ODBC和Access通讯。在实际应用中,调用后台存储过程不方便,花费时间也长。有什么好办法可以在
- XML同HTML一样,都来自Standard Generalized Markup Language, 即标准通用标记语言,简称SGML。早
- golang并没有像C语言一样提供三元表达式。三元表达式的好处是可以用一行代码解决原本需要多行代码才能完成的功能,让冗长的代码瞬间变得简洁。
- 关于“登录”和“注册”的问题已经被很多设计师和交互设计上写过无数遍了,今天我在登录纳米盘网站时受到打击了所以写下此文。事情是这样的:当初租用
- 这片文章大体概括了一些设计网页中的大问题。希望能给你做下一个网页时给予一些儿启发。1、记住:你能掌控的时间是有限的我仅仅用4秒钟就能浏览完平
- 微软今天宣布正式发布SQL Server 2008服务器软件,这将帮助微软与Oracle 11g,IBM DB2 9.5数据库产品对抗.此前
- 如何用Response.Write调用代替内嵌表达式?我们可以利用下面的代码,注意:代码的每一行对响应流有一次写操作,所有的代码都包含在一个
- “重构”的春风吹遍大江南北,互联网一时间风声鹤唳,“div+CSS”俨然已成为一种“时尚”,难以尽数的网站都不约而同地开始了自己的“重构”。
- <!--模板--> <table width="100%" borde
- 第三章 XML的术语提纲:导言 一.XML文档的有关术语 二.DTD的有关术语导言初学XML最令人头疼的就是有一大堆新的术语概念要理解。由于
- 本文实例讲述了php使用pthreads v3多线程实现抓取新浪新闻信息。分享给大家供大家参考,具体如下:我们使用pthreads,来写一个
- 一、为表创建自增长自段有两种,一种是不同的表使用各自的Sequence,方法如下: 1、在Oracle sequence首先创建sequen
- 最近朋友需要一个可以识别图片中的文字的程序,以前做过java验证码识别的程序;刚好最近在做一个python项目,所以顺便用Python练练手
- 在曾经的 淘宝UED 招聘 中有这样一道题目:“使用纯CSS实现未知尺寸的图片(但高宽都小于200px)在200px的正方形容器中水平和垂直
- jxdawei的个人博客:http://www.iwcn.net本文目的:与您分享如何学习基于web标准的网页制作。适合人群:网页制作初学者