13.5. base64 — 使用 ascii 编码二进制数据 | 互联网数据处理 |《python 3 标准库实例教程》| python 技术论坛-大发黄金版app下载

未匹配的标注

目标:base64 模块含有一些可将二进制数据转译为用 ascii 子集编码数据的函数,使得这些数据可以用纯文本协议来传递。

base64 , base32 , base16 和 base85 编码将 8 位的单字节转换成 ascii 范围内可打印的字符值,来兼容那些只支持 ascii 编码数据的系统,代价是使用更多的位来表示数据,比如 smtp 。 base 的值表示每个字母在编码中所需要的相应的长度。一些使用略有不同的字母表,但仍然是 url-安全的原编码系统的变种也是存在的。

base 64 编码

这是用来编码文本的一个基本例子.

base64_b64encode.py

import base64
import textwrap
# 读取源文件并去掉头部。
with open(__file__, 'r', encoding='utf-8') as input:
    raw = input.read()
    initial_data = raw.split('#end_pymotw_header')[1]
byte_string = initial_data.encode('utf-8')
encoded_data = base64.b64encode(byte_string)
num_initial = len(byte_string)
# 填充字节不超过两个
padding = 3 - (num_initial % 3)
print('{} bytes before encoding'.format(num_initial))
print('expect {} padding bytes'.format(padding))
print('{} bytes after encoding\n'.format(len(encoded_data)))
print(encoded_data)

输入必须是字节串,因此 unicode 字符串首先用 utf-8 编码。输出显示原本 185 个字节(按输出来看应该是 184 个字节)的 utf-8 源数据被扩展编码为 248 个字节。

注意

由库函数编码后的数据是不包含换行符的,但我们人为地将其断行是为了在页面上更好地展示输出。

$ python3 base64_b64encode.py
184 bytes before encoding
expect 2 padding bytes
248 bytes after encoding
b'cmltcg9ydcbiyxnlnjqkaw1wb3j0ihrlehr3cmfwcgojiexvywqgdghpcybzb3
vyy2ugzmlszsbhbmqgc3ryaxagdghlighlywrlci4kd2l0acbvcgvukf9fzmlszv
9flcancicsigvuy29kaw5npsd1dgytoccpigfzigluchv0ogogicagcmf3id0gaw
5wdxqucmvhzcgpciagicbpbml0awfsx2rhdgegpsbyyxcuc3bsaxqojw=='

base 64 解码

b64decode() 将编译后的字符串还原成原来的形式,即用查表的方式将四个字节换为原本的三个。

base64_b64decode.py

import base64
encoded_data = b'vghpcybpcyb0agugzgf0yswgaw4gdghlignszwfylg=='
decoded_data = base64.b64decode(encoded_data)
print('encoded :', encoded_data)
print('decoded :', decoded_data)

在编码过程中,输入的每 24 位(每三个字节)组成一个序列,该序列在输出中都被替换为四个字节。输出末尾处的等号仅表示填充,因为本例中,原字符串的位长度不被 24 整除。

$ python3 base64_b64decode.py
encoded : b'vghpcybpcyb0agugzgf0yswgaw4gdghlignszwfylg=='
decoded : b'this is the data, in the clear.'

b64decode() 返回的值是一个字节串。如果已知内容是文本,那么字节串可以被转换成一个 unicode 对象。然而,用 base 64 编码的意义在于传递二进制数据,因此假定解码后的值是文本并不总是安全的。

url-安全变种

由于默认的 base64 字母表包含  / 这两个字符,而它们在 urls 中也会被用到,因此有必要采用另一种编码方式来替换这些字符。

base64_urlsafe.py

import base64
encodes_with_pluses = b'\xfb\xef'
encodes_with_slashes = b'\xff\xff'
for original in [encodes_with_pluses, encodes_with_slashes]:
    print('original         :', repr(original))
    print('standard encoding:',
          base64.standard_b64encode(original))
    print('url-safe encoding:',
          base64.urlsafe_b64encode(original))
    print()

 被替换为 - ,而 / 则被替换为下划线 (_) 。其他字符保持不变。

$ python3 base64_urlsafe.py
original         : b'\xfb\xef'
standard encoding: b'  8='
url-safe encoding: b'--8='
original         : b'\xff\xff'
standard encoding: b'//8='
url-safe encoding: b'__8='

其他编码

除了 base64 编码,该模块还提供了其他一些函数来处理 base85 ,base32 和 base16 (hex) 编码的数据.

base64_base32.py

import base64
original_data = b'this is the data, in the clear.'
print('original:', original_data)
encoded_data = base64.b32encode(original_data)
print('encoded :', encoded_data)
decoded_data = base64.b32decode(encoded_data)
print('decoded :', decoded_data)

base32 字母表包含 ascii 中所有 26 个大写字母和数字 2 到 7 。

$ python3 base64_base32.py
original: b'this is the data, in the clear.'
encoded : b'krugs4zanfzsa5dimuqgiylumewca2loeb2gqzjamnwgkylsfy==
===='
decoded : b'this is the data, in the clear.'

base16 函数则可以处理十六进位制字母表。

base64_base16.py

import base64
original_data = b'this is the data, in the clear.'
print('original:', original_data)
encoded_data = base64.b16encode(original_data)
print('encoded :', encoded_data)
decoded_data = base64.b16decode(encoded_data)
print('decoded :', decoded_data)

每当减少编码一个字母所用的位数时,编码后的数据就需要更多的空间。

$ python3 base64_base16.py
original: b'this is the data, in the clear.'
encoded : b'546869732069732074686520646174612c20696e207468652063
6c6561722e'
decoded : b'this is the data, in the clear.'

base85 函数则使用了在空间利用率上面比 base64 更高效的扩展字母表。

base64_base85.py

import base64
original_data = b'this is the data, in the clear.'
print('original    : {} bytes {!r}'.format(
    len(original_data), original_data))
b64_data = base64.b64encode(original_data)
print('b64 encoded : {} bytes {!r}'.format(
    len(b64_data), b64_data))
b85_data = base64.b85encode(original_data)
print('b85 encoded : {} bytes {!r}'.format(
    len(b85_data), b85_data))
a85_data = base64.a85encode(original_data)
print('a85 encoded : {} bytes {!r}'.format(
    len(a85_data), a85_data))

在 mercurial , git 和 pdf 文件格式中使用的 base85 编码存在多个不同变种。python 实现了其中两种, b85encode() 实现的是在 git 和 mercurial 中使用的版本,而 a85encode() 实现的则是在 pdf 文件中使用的 ascii85 变种。

$ python3 base64_base85.py
original    : 31 bytes b'this is the data, in the clear.'
b64 encoded : 44 bytes b'vghpcybpcyb0agugzgf0yswgaw4gdghlignszwf
ylg=='
b85 encoded : 39 bytes b'ra^~)azc?tbzbkdwmon effuaaarpday*k0vr9}
'
a85 encoded : 39 bytes b'< oue dgm>fd,5.a79rg/0jye ev:. cf5!@<*t
'

参考

  •  -- base16, base32 和 base64 数据编码
  •  -- 一份 ipv6 地址的简约表示 (建议使用 base-85 编码 ipv6 网址)

本文章首发在 大发黄金版app下载 网站上。

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 cc 协议,如果我们的工作有侵犯到您的权益,请及时联系大发黄金版app下载。

原文地址:https://learnku.com/docs/pymotw/base64-e...

译文地址:https://learnku.com/docs/pymotw/base64-e...

上一篇 下一篇
讨论数量: 0



暂无话题~
网站地图