python I/O+编码 小例

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提供的接口是通用的,唯一不同的就是介质变了。

猜你喜欢

转载自blog.csdn.net/qq_21294095/article/details/85172591
今日推荐