base64 使用 ASCII 编码二进制数据
base64, base32, base16 和 base85 编码函数将 8 位字符转换为 ASCII 码的可打印字符,这样可以让那些只支持 ASCII 的系统(例如 SMTP) 也可以传输任意二进制数据,代价是需要使用更多的比特来表示. base 后面的数字表示每次编码时使用的字母长度. 除了这些函数之外,还有 URL 安全的变体其使用的字母与原函数会有少许变化。
1Base64 的编码函数
下面是一个编码文本的例子
# base64_b64encode.py
import base64
import textwrap
# Load this source file and strip the header.
with open("base64_b64encode.py", '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)
# There will never be more than 2 padding bytes.
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)
394 bytes before encoding Expect 2 padding bytes 528 bytes after encoding b'JylbMV0KCmJ5dGVfc3RyaW5nID0gaW5pdGlhbF9kYXRhLmVuY29kZSgndXRmLTgnKQplbmNvZGVkX2RhdGEgPSBiYXNlNjQuYjY0ZW5jb2RlKGJ5dGVfc3RyaW5nKQoKbnVtX2luaXRpYWwgPSBsZW4oYnl0ZV9zdHJpbmcpCgojIFRoZXJlIHdpbGwgbmV2ZXIgYmUgbW9yZSB0aGFuIDIgcGFkZGluZyBieXRlcy4KcGFkZGluZyA9IDMgLSAobnVtX2luaXRpYWwgJSAzKQoKcHJpbnQoJ3t9IGJ5dGVzIGJlZm9yZSBlbmNvZGluZycuZm9ybWF0KG51bV9pbml0aWFsKSkKcHJpbnQoJ0V4cGVjdCB7fSBwYWRkaW5nIGJ5dGVzJy5mb3JtYXQocGFkZGluZykpCnByaW50KCd7fSBieXRlcyBhZnRlciBlbmNvZGluZ1xuJy5mb3JtYXQobGVuKGVuY29kZWRfZGF0YSkpKQpwcmludChlbmNvZGVkX2RhdGEpCg=='
b64 函数只接受 byte 字符串,因此 unicode 格式的字符串必须首先被编码成 UTF-8 格式的 byte 字符串. 上面代码的输出结构显示,UTF-8 格式的源字符串是 394 个字节,而转成 BASE64 格式后扩展为 528 个字节了。
2Base64 的解码函数
b64decode() 将编码后的字符串转换回源格式,方法是每次截取 4 个字节然后根据检查表将之转换成原始的 3 个字节的字符串。
# base64_b64decode.py
import base64
encoded_data = b'VGhpcyBpcyB0aGUgZGF0YSwgaW4gdGhlIGNsZWFyLg=='
decoded_data = base64.b64decode(encoded_data)
print('Encoded :', encoded_data)
print('Decoded :', decoded_data)
Encoded : b'VGhpcyBpcyB0aGUgZGF0YSwgaW4gdGhlIGNsZWFyLg==' Decoded : b'This is the data, in the clear.'
编码的过程是每次从输入中读取 24 个比特(即 3 个字节),然后将这 24 个比特平均划分成 4 个字节,这 4 个字节就是转码后的输出结果. 上面的例子中,输出结果最后插入了=号,这是因为原始字符串中的比特数并不能被 24 整除。
b64decode() 函数返回的结果是一个 byte 字符串. 若其结果已知是文本,则可以将该 byte 字符串转换为 unicode 对象. 然而,base64 常常用于编码二进制数据,因此不能总是认为解码的结果就是文本。
3URL-safe Variations
由于莫的 base64 编码字母中包含了+和/, 而这两个字母存在于 URL 中,因此常常需要使用其他字母来代替这两个字母。
# 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()
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='
可以看到,结果中的+替换成了-,/替换成了_. 其他字母不变。
4其他的编码函数
除了 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)
Original: b'This is the data, in the clear.' Encoded : b'KRUGS4ZANFZSA5DIMUQGIYLUMEWCA2LOEB2GQZJAMNWGKYLSFY======' Decoded : b'This is the data, in the clear.'
Base32 字母表包含了 ASCII 字符集中的 26 个大写字母以及 2 到 7 的数字。
Base16 函数则使用 16 进制字母来表示数据。
# 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)
Original: b'This is the data, in the clear.' Encoded : b'546869732069732074686520646174612C20696E2074686520636C6561722E' 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))
Original : 31 bytes b'This is the data, in the clear.' b64 Encoded : 44 bytes b'VGhpcyBpcyB0aGUgZGF0YSwgaW4gdGhlIGNsZWFyLg==' b85 Encoded : 39 bytes b'RA^~)AZc?TbZBKDWMOn+EFfuaAarPDAY*K0VR9}' a85 Encoded : 39 bytes b'<+oue+DGm>FD,5.A79Rg/0JYE+EV:.+Cf5!@<*t'
有许多 Base85 编码函数的变体. 像 Mercurial, git 以及 PDF file 中使用的都是不同的变体. Python 中包含了两种实现方法: b85encode() 实现了 Git 和 Mercurial 中使用的版本,而 a85encode() 实现了 Ascii85 的变体,该变体用于 PDF 文件中。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论