字符编码

什么是字符编码:

我们平时在使用计算机时,用的都是人类能读懂的字符(用高级语言编程的结果也无非是在文件内写了一堆字符),如何能让计算机读懂人类的字符?

必须经过一个过程:

  • 字符 --------》翻译过程 -------》数字

总而言之,字符编码是将人类的字符编码成计算机能识别的数字,这种转换必须遵循一套固定的标准,该标准无非是人类字符与数字的对应关系,称之为字符编码表。

字符编码的发展:

计算机由美国人发明,最早的字符编码为ASCII,只规定了英文字母数字和一些特殊字符与数字的对应关系。最多只能用 8 位来表示(一个字节),即:2**8 = 256,所以,ASCII码最多只能表示 256 个符号。当然我们编程语言都用英文没问题,ASCII够用,但是在处理数据时,不同的国家有不同的语言,中国人会加入中文,日本人会在自己的程序中加入日文,韩国人也是。

但是要表示中文,单拿一个字节表表示一个汉子,是不可能表达完的(连小学生都认识两千多个汉字),解决方法只有一个,就是一个字节用>8位2进制代表,位数越多,代表的变化就多,这样,就可以尽可能多的表达出不通的汉字。

所以中国人规定了自己的标准gb2312编码,规定了包含中文在内的字符与数字的对应关系。

日本人规定了自己的Shift_JIS编码;韩国人规定了自己的Euc-kr编码(另外,韩国人说,计算机是他们发明的,要求世界统一用韩国编码,但世界人民没有搭理他们)。

这时候问题出现了,精通18国语言的小周同学谦虚的用8国语言写了一篇文档,那么这篇文档,按照哪国的标准,都会出现乱码(因为此刻的各种标准都只是规定了自己国家的文字在内的字符跟数字的对应关系,如果单纯采用一种国家的编码格式,那么其余国家语言的文字在解析时就会出现乱码)。所以迫切需要一个世界的标准(能包含全世界的语言)于是Unicode应运而生(韩国人表示不服,然后没有什么卵用)。

ascii用1个字节(8位二进制)代表一个字符;Unicode常用2个字节(16位二进制)代表一个字符,生僻字需要用4个字节。

例:字母x,用ascii表示是十进制的120,二进制0111 1000。

汉字中已经超出了ASCII编码的范围,用Unicode编码是十进制的20013,二进制的01001110 00101101。

字母x,用Unicode表示二进制0000 0000 0111 1000,所以Unicode兼容ascii,也兼容万国,是世界的标准。

这时候乱码问题消失了,所有的文档我们都使用但是新问题出现了,如果我们的文档通篇都是英文,你用Unicode会比ascii耗费多一倍的空间,在存储和传输上十分的低效。

本着节约的精神,又出现了把Unicode编码转化为“可变长编码”的UTF-8(Unicode Transformation Format-8)编码。UTF-8编码把一个Unicode字符根据不同的数字大小编码成1-6个字节,常用的英文字母被编码成1个字节,汉字通常是3个字节,只有很生僻的字符才会被编码成4-6个字节。如果你要传输的文本包含大量英文字符,用UTF-8编码就能节省空间:

乱码分析:

首先明确概念

  • 文件从内存刷到硬盘的操作简称存文件
  • 文件从硬盘读到内存的操作简称读文件

乱码的两种情况:

  • 乱码一:存文件时就已经乱码

存文件时,由于文件内有各个国家的文字,我们单以shiftjis去存,
本质上其他国家的文字由于在shiftjis中没有找到对应关系而导致存储失败。但当我们硬要存的时候,编辑并不会报错(难道你的编码错误,编辑器这个软件就跟着崩溃了吗???),但毫无疑问,不能存而硬存,肯定是乱存了,即存文件阶段就已经发生乱码,而当我们用shiftjis打开文件时,日文可以正常显示,而中文则乱码了。

  • 乱码二:存文件时不乱码而读文件时乱码

存文件时用utf-8编码,保证兼容万国,不会乱码,而读文件时选择了错误的解码方式,比如gbk,则在读阶段发生乱码,读阶段发生乱码是可以解决的,选对正确的解码方式就ok了。

基本文件操作

一、什么是文件?

文件是操作系统为用户或应用程序提供的一个读写硬盘的虚拟单位。文件的操作是基于文件,即文件的操作核心就是:读和写。也

就是只要我们想要操作文件就是对操作系统发起请求,然后由操作系统将用户或应用程序对文件的读写操作转换成集体的硬盘指令(比如控制盘片转动,控制机械手臂移动,以此来读取数据)。

二、为什么要有文件

内存无法永久保存数据,但凡我们想要永久保存数据都需要把文件保存到硬盘中,而操作文件就可以实现对硬件的操作。

三、如何使用文件

3.1通过硬盘读取数据

通过硬盘来读取数据,python中可以使用open()方法打开某个具体的文件,open()方法内写入文件路径

#打开文件
open(r'/Users/mac/desktop/jupyter/pythonCourseware/32.txt')

3.2写入数据,使用write写入

# write模式打开文件
f = open(r'/Users/mac/desktop/jupyter/pythonCourseware/32.txt', mode='w')
f.write("""name = 'nick'
pwd = '123'""")
f.close()
f = open(r'/Users/mac/desktop/jupyter/pythonCourseware/32.txt', mode='r')
data = f.read()
print(data)
name = 'nick'

with管理文件操作上下文

之前我们使用open()方法操作文件,但是open打开文件后我们还需要手动释放文件对操作系统的占用。但是其实我们可以更方便的打开文件,即Python提供的上下文管理工具——with open()。

with open('32.txt', 'rt', encoding='utf8') as f:
    print(f.read())

也可以通过逗号分割,一次性打开多个文件

with open('32.txt', 'rb') as fr, \
        open('35r.txt', 'wb') as fw:
    f.write(f.read())

四、总结

  1. 打开文件
  2. 读写
  3. 关闭

文件的打开模式

文件有三种操作模式

  • r模式为read 只能读不能写,文件不在时会报错

    # rt: read by text
    # windows的操作系统默认编码为gbk,因此需要使用utf8编码
    f = open('32.txt', mode='rt', encoding='utf8')
    data = f.read() #读取
    print(data)
    print(f"type(data): {type(data)}")
    f.close()
    
  • w模式为write 只能写,不能读,文件存在的时候回清空文件后再写入内容;文件不存在的时候会创建文件后写入内容。

    # wt
    f = open('34w.txt', mode='wt', encoding='utf8')
    print(f"f.readable(): {f.readable()}")
    f.write(' 真帅呀\n')  # '\n'是换行符
    f.write(' you drop, I drop.')
    f.write(' 帅的我五体投地')
    f.flush()  # 立刻将文件内容从内存刷到硬盘
    f.close()
    
  • a模式为append可以追加。文件存在,则在文件的末端写入内容;文件不存在的时候会创建文件后写入内容。

    # at
    f = open('34a.txt', mode='at', encoding='utf8')
    print(f"f.readable(): {f.readable()}")
    f.write(' 真帅呀\n')  # '\n'是换行符
    f.write(' you drop, I drop.')
    f.write(' 帅的我五体投地')
    f.close()
    

文件内容的格式有两种

  • t模式为text
  • b模式为bytes

需要注意的是:t、b这两种模式均不能单独使用,都需要与r/w/a之一连用。

路径

一、相对路径

  • Windows系统绝对路径从盘符(C:\、D:\)开始写一个完整的路径。

二、相对路径

相对于当前执行文件所在的文件夹开始找。

f = open('32.txt')  # 32.txt与该.md文档同路径位置