-
GBK、Unicode、UTF都可以看做编码集,每一个数字代表一个字符。其中utf-8作为Unicode的优化,减少了纯英文字符的字节数。
-
计算机在内存中都使用Unicode编码,在输出时转化为GBK/UTF-8编码。在python3中也是这样的。
-
假设一个非常简单的流程:从一个GBK编码的文件读出,写到一个以UTF-8编码的文件。
其中数据的流动是这样的:
a. 读:open按照GBK的编码,两个字节两个字节的读出一个个汉字,然后将其以Unicode编码存在内存里;
b. 写:把内存中的Unicode编码的字节序列解码,再编码成UTF-8的字节,写入到硬盘中。 -
上面一些实验的代码:
#%%
s = '啊' # = '\u554a'
print(s.encode('utf-8')) # b'\xe5\x95\x8a'
print(s.encode('gbk')) # b'\xb0\xa1'
assert ord(s) == 0x554a
#%%
# 将内存中Unicode字符串按照不同编码写进文件中
with open('gbk.txt', 'w', encoding='gbk') as gbk, open('utf.txt', 'w', encoding='utf-8') as utf:
gbk.write(s)
utf.write(s)
# 此时gbk.txt里两个字节:0xb0 0xa1,
# utf.txt里三个字节:0xe5 0x95 0x8a
# 必须按照相应的编码读
with open('gbk.txt', 'r', encoding='gbk') as gbk, open('utf.txt', 'r', encoding='utf-8') as utf:
gbk_s = gbk.read()
utf_s = utf.read()
print(gbk_s, utf_s)
assert gbk_s == utf_s
assert gbk_s == '\u554a'
#%%
# 否则会报UnicodeDecodeError,因为GBK存进去的两个字节,UTF-8识别不了
with open('gbk.txt', 'r', encoding='utf-8') as f:
f.read()
# UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb0 in position 0: invalid start byte
#%%
# 先查看utf.txt文件中的字节
with open('utf.txt', 'rb') as utf:
print(utf.read()) # b'\xe5\x95\x8a'
# 将utf8编码的文件读取出来按GBK存进文件中
with open('utf.txt', 'r', encoding='utf-8') as utf:
s = utf.read()
print(hex(ord(s))) # 0x55a4 说明是Unicode编码
# 将s写入按GBK编码的文件
with open('gbk.txt', 'w', encoding='gbk') as gbk:
gbk.write(s)
# 查看gbk.txt文件中的字节
with open('gbk.txt', 'rb') as gbk:
print(gbk.read()) # b'\xb0\xa1' 为UTF-8编码后的字节