python3使用Unicode编码
str = ord('中') #ord获取字符整数表示 这个整数表示也就是Unicode编码去映射的 也就是'中'字在内存中真正表示的值
print(str)
#在内存中以Unicode表示,一个字符对应若干个字节。如果要在网络上传输,或者保存到磁盘上,就需要把str变为以字节为单位的bytes
str = '中文'.encode('utf-8') #把Unicode字符串编码成utf-8的bytes
print(str)
#decode把utf-8编码的bytes解码成Unicode字符串
str = b'\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8') #'中文'的utf-8编码的bytes
print(str)
output:
20013
b'\xe4\xb8\xad\xe6\x96\x87'
中文
配合编码进行I/0:
with open('msg.txt', 'wb') as file:
s = '中文'.encode('UTF-8')
file.write(s) #二进制打开文件 必须写入bytes 字节数组类型,并且不能指定encoding
with open('msg.txt', 'w', encoding='UTF-8') as file:
s = '中文' #字符形式打开文件 写入的就直接是str类型 按照给定的encoding去写
file.write(s)
可以看到,如果以二进制形式打开文件,那么就需要用到上面所说的encode和decode。
这个扩展到读文件,还有网络流读写都是一样的。理解了最简单的例子,才能往复杂的去写,不然越写越糊涂。
再来看个例子,在内存中读写,原理是一模一样的,不过数据交换从内存和硬盘变成了内存和内存:
from io import StringIO
with StringIO() as s:
s.write('hello')
s.write(' ')
s.write('world!') #seek已经定位到11 读写都会改变seek 就像文件里的游标一样
print(s.getvalue())
with StringIO('''你好
世界!''') as s: #如果想重新读上面写好的StringIO 那么用seek(0)重新定位即可
ls = s.readlines()
for l in ls:
print(l,end='')
Output:
hello world!
你好
世界!
一样的字符流,为什么这里字符流不需要指定编码?其实之前我有篇博客你真的明白Java和Python3使用Unicode编码的含义吗?已经详细解释过了,这个是因为python在内存中就是使用的Unicode编码,我们没法去改变,而文件是存储在硬盘上的,可以有多种编码方式,所以当指定字符流写入的时候,可以添加encoding字段来指定文件的编码方式。
当然,如果你执意如此,你可以把字符串decode,然后再转回字符串,就像下面这样,不过,何必呢?
from io import StringIO
with StringIO() as s:
a = str('中国'.encode('UTF-8'))
s.write(a)
print(s.getvalue())
Output:
b'\xe4\xb8\xad\xe5\x9b\xbd'
其实当你要这样用的时候,需要选择字节流BytesIO
from io import BytesIO
with BytesIO() as b:
b.write('中国'.encode('UTF-8'))
print(b.getvalue())
with BytesIO(b'\xe4\xb8\x87\xe5\xb2\x81') as b:
ls = b.readlines()
for l in ls:
print(l.decode(), end='')
Output:
b'\xe4\xb8\xad\xe5\x9b\xbd'
万岁
可以看到,当改变通信介质之后,python提供的接口是通用的,唯一不同的就是介质变了。