Bit与字节详解及Python编码进制操作
Bit和字节
bit(比特)是binary digit的英文缩写,量度信息的单位,也是表示信息量的最小单位,只有0、1两种二进制状态。 byte字节是内存中基本的存储单位。每个英文字符都是一个字节,汉字有多个字节组成。
我们在使用计算机过程中接触最多的也是字节:
- ipv4是由32位,4个字节组成 192.168.31.1
- ipv6是由128位,16个字节组成 fe80::d66d:5fbe:99c1:fe45%7
我们看到电脑磁盘上的文件都会标注大小多少k、多少m的。
- 1KB = 1024byte
- 1MB = 1024KB = 1024 * 1024byte
- 1GB = 1024MB = 1024 * 1024 * 1024byte
- 1TB = 1024GB = 1024 * 1024 * 1024 * 1024byte
- 1PB = 1024TB = 1024 * 1024 * 1024 * 1024 * 1024byte
- 1EB = 1024PB = 1024 * 1024 * 1024 * 1024 * 1024 * 1024byte
我们在开发过程中很多时候用到数据库,整型一般32位4个字节,下面的字符串是32个字节, tinyint是1个字节,char 11个字节。
如果一行数据写满的话(4+32 + 1 + 1 +11)
100w行记录,大概50m左右,只有了解这些,在计算机数据吞吐量非常有用。
基础知识
一个字节可表示的范围是 0 ~ 255(十六进制:0x00 ~ 0xFF)
ASCII值范围 0 ~ 127(十六进制:0x00~0x7F),ASCII有 95 个可见字符范围 (32~126) 超越 ASCII范围的 128~255(十六进制:0x80 ~ 0xFF)之间的值是不可见字符。
在 Python 中,字节和字符有不同的表示形式:
- 字节:使用 bytes 类型表示,通常用于处理二进制数据。
- 字符:使用 str 类型表示,通常用于处理文本数据。
# 字节
byte_data = b'Hello'
print(byte_data) # 输出: b'Hello'
# 字符
char_data = 'Hello'
print(char_data) # 输出: Hello
字节和字符之间的转换
从字符串到字节:使用 encode 方法。 从字节到字符串:使用 decode 方法。
# 字符串到字节
char_data = 'Hello'
byte_data = char_data.encode('utf-8')
print(byte_data) # 输出: b'Hello'
# 字节到字符串
byte_data = b'Hello'
char_data = byte_data.decode('utf-8')
print(char_data) # 输出: Hello
Python 进制表示与转换
Python 提供了内置函数来处理二进制、八进制和十六进制数:
- 二进制:前缀 0b 或 0B
- 八进制:前缀 0o 或 0O
- 十六进制:前缀 0x 或 0X
# 二进制
binary_num = 0b1010 # 二进制 1010 等于十进制 10
print(binary_num) # 输出: 10
# 八进制
octal_num = 0o12 # 八进制 12 等于十进制 10
print(octal_num) # 输出: 10
# 十六进制
hex_num = 0xA # 十六进制 A 等于十进制 10
print(hex_num) # 输出: 10
数字之间的转换
十进制到其他进制:使用 bin、oct 和 hex 函数。 其他进制到十进制:使用 int 函数。
# 十进制到其他进制
decimal_num = 10
print(bin(decimal_num)) # 输出: 0b1010
print(oct(decimal_num)) # 输出: 0o12
print(hex(decimal_num)) # 输出: 0xa
# 其他进制到十进制
binary_str = '1010'
octal_str = '12'
hex_str = 'A'
print(int(binary_str, 2)) # 输出: 10
print(int(octal_str, 8)) # 输出: 10
print(int(hex_str, 16)) # 输出: 10
ASCII 编码
ASCII 编码是一种字符编码标准,用于将字符转换为数字(通常是 7 位或 8 位二进制数)。
字符到 ASCII 码:使用 ord 函数。 ASCII 码到字符:使用 chr 函数。
# 字符到 ASCII 码
char = 'A'
ascii_code = ord(char)
print(ascii_code) # 输出: 65
# ASCII 码到字符
ascii_code = 65
char = chr(ascii_code)
print(char) # 输出: A
base64
web开发或者网络传输中,无论是字符流的文本数据,还是字节流的(图片、语音、视频)的数据。我们都可以先通过base64转化为可见字符,再做传输,接收方再做解码操作,还原数据本身类型。
编码、解码
import base64
# \x80 换成十进制为 128,超越了 ascii 范围,为不可见字节
data = b"\x80"
datab64 = base64.b64encode(data) # 编码为 base64 的可见字节
print(datab64) # b'gA=='
data = base64.b64decode(datab64)
print(data) # 解码为不可见字节 b'\x80'
通过base64可把可见、不可见字节都编码为可见字节
import base64
dataone = "p".encode("utf8") # 可见字节
datatwo = "你".encode("utf8") # 不可见字节
print(base64.b64encode(dataone)) # 编码为可见字节 b'cA=='
print(base64.b64encode(datatwo)) # 编码为可见字节 b'5L2g'
base64 编码会把 3 个字节的字节类型数据编码为 4 个可见字节的字节类型数据。 如果字符长度不是3的倍数,后面用=补齐
import base64
s = "hello朋友"
# 预先计算字符串的字节序列
byte_sequence = s.encode("utf-8")
for i in range(len(s)):
si = i + 1
bt = byte_sequence[:si]
basedata = base64.b64encode(bt)
bq = len(bt) % 3
wz = (3 - bq) if bq != 0 else 0
print(f'{len(bt)}个字节,可见字符{basedata} \
长度{len(basedata)}, \
3个字节补齐{wz}位{"=" * wz}')
查看输出结果,我们会看到补齐情况 1个字节,可见字符b'aA=='长度4,3个字节补齐2位== 2个字节,可见字符b'aGU='长度4,3个字节补齐1位= 3个字节,可见字符b'aGVs'长度4,3个字节补齐0位 4个字节,可见字符b'aGVsbA=='长度8,3个字节补齐2位== 5个字节,可见字符b'aGVsbG8='长度8,3个字节补齐1位= 6个字节,可见字符b'aGVsbG/m'长度8,3个字节补齐0位 7个字节,可见字符b'aGVsbG/mnA=='长度12,3个字节补齐2位==
base64 编码后可能出现字符 + 和 /,在网页上传输数据,我们用 get 方式传输字符串时,字符 + 和 / 在 URL 中有特殊用途,就不能直接作为参数,所以又有一种 url safe 的 base64 编码,其实就是把字符 + 和 / 分别变成 - 和 _。
import base64
mydata = b"\xfb\xef\xff"
# 编码为 ++//,但是 + 和 / 在 url 中有特殊用途,不能作为参数
print(base64.b64encode(mydata))
print(base64.urlsafe_b64encode(mydata)) # 编码为 --__
Base64 仅仅是把字节类型数据按照一定的算法转化为属于 ASCII 范围内的可见字节类型数据。由于Base64 都是通用的,我们在数据加密中不要使用。