Python基础(5)_字符编码、文件处理
一、文件读取过程:
1. 文本编辑器存取文件的原理(nodepad++,pycharm,word)
打开编辑器就打开了启动了一个进程,是在内存中的,所以在编辑器编写的内容也都是存放与内存中的,断电后数据丢失,因而需要保存到硬盘上,点击保存按钮,就从内存中把数据刷到了硬盘上。
在这一点上,我们编写一个py文件(没有执行),跟编写其他文件没有任何区别,都只是在编写一堆字符而已。
2. python解释器执行py文件的原理 ,例如python test.py
第一阶段:python解释器启动,此时就相当于启动了一个文本编辑器
第二阶段:python解释器相当于文本编辑器,去打开test.py文件,从硬盘上将test.py的文件内容读入到内存中
第三阶段:python解释器解释执行刚刚加载到内存中test.py的代码
总结:
- python解释器是解释执行文件内容的,因而python解释器具备读py文件的功能,这一点与文本编辑器一样
- 与文本编辑器不一样的地方在于,python解释器不仅可以读文件内容,还可以执行文件内容
二、字符编码
1、字符编码的作用:程序员用字符编程,而计算机只能识别二进制0、1,因此字符编码的作用是将人操作的字符,翻译成计算机能识别的二进制数字
即、
字符--------(翻译过程)------->数字
这个过程实际就是一个字符如何对应一个特定数字的标准,这个标准称之为字符编码
2、字符编码的发展史
阶段一:现代计算机起源于美国,最早诞生也是基于英文考虑的ASCII
ASCII:一个Bytes代表一个字符(英文字符/键盘上的所有其他字符),1Bytes=8bit,8bit可以表示0-2**8-1种变化,即可以表示256个字符
阶段二:为了满足中文,中国人定制了GBK
GBK: 2Bytes代表一个字符
为了满足其他国家,各个国家纷纷定制了自己的编码
日本把日文编到Shift_JIS
里,韩国把韩文编到Euc-kr
里
阶段三:各国有各国的标准,就会不可避免地出现冲突,结果就是,在多语言混合的文本中,显示出来会有乱码。于是产生了unicode
Unicode:统一用2Bytes代表一个字符,2**16-1=65535,可代表6万多个字符,因而兼容万国语言,其缺点是:对于通篇都是英文的文本来说,占内存较大
UTF-8:解决占内存较大的问题,对英文字符只用1Bytes表示,对中文字符用3Bytes
总结:
Unicode:简单粗暴,所有字符都是2Bytes,优点是字符->数字的转换速度快,缺点是占用空间大
utf-8:精准,对不同的字符用不同的长度表示,优点是节省空间,缺点是:字符->数字的转换速度慢,因为每次都需要计算出字符需要多长的Bytes才能够准确表示
Unicode和utf-8应用:
1、内存中使用的编码是unicode,用空间换时间(程序都需要加载到内存才能运行,因而内存应该是尽可能的保证快)
2、硬盘中或者网络传输用utf-8,网络I/O延迟或磁盘I/O延迟要远大与utf-8的转换延迟,而且I/O应该是尽可能地节省带宽,保证数据传输的稳定性。
3、字符编码的使用
从内存往硬盘存文件:encode
内存从硬盘读取文件:decode
文件乱码情况分析:
乱码一:存文件时就已经乱码。例如中文汉字以日文编码shiftjis去存,此乱码无法恢复
乱码二:存文件时不乱码而读文件时乱码。存文件时用utf-8编码,保证兼容万国,不会乱码,而读文件时选择了错误的解码方式,比如gbk,则在读阶段发生乱码,此乱码可恢复,选对正确的解码方式就ok了
总结:
无论是何种编辑器,要防止文件出现乱码(请一定注意,存放一段代码的文件也仅仅只是一个普通文件而已,此处指的是文件没有执行前,我们打开文件时出现的乱码)核心法则就是,文件以什么编码保存的,就以什么编码方式打开
4、程序的执行
阶段一:启动python解释器
阶段二:python解释器此时就是一个文本编辑器,负责打开文件test.py,即从硬盘中读取test.py的内容到内存中
此时,python解释器会读取test.py的第一行内容,#coding:utf-8,来决定以什么编码格式来读入内存,这一行就是来设定python解释器这个软件的编码使用的编码格式这个编码,可以用sys.getdefaultencoding()查看,如果不在python文件指定头信息#-*-coding:utf-8-*-,那就使用默认的
python2中默认使用ascii,python3中默认使用utf-8
阶段三:读取已经加载到内存的代码(unicode编码的二进制),然后执行,执行过程中可能会开辟新的内存空间,比如x="egon"
内存的编码使用unicode,不代表内存中全都是unicode编码的二进制,在程序执行之前,内存中确实都是unicode编码的二进制,比如从文件中读取了一行x="egon",其中的x,等号,引号,地位都一样,都是普通字符而已,都是以unicode编码的二进制形式存放与内存中的
但是程序在执行过程中,会申请内存(与程序代码所存在的内存是俩个空间),可以存放任意编码格式的数据,比如x="egon",会被python解释器识别为字符串,会申请内存空间来存放"hello",然后让x指向该内存地址,此时新申请的该内存地址保存也是unicode编码的egon,如果代码换成x="egon".encode('utf-8'),那么新申请的内存空间里存放的就是utf-8编码的字符串egon了
5、在python3中有两种字符串类型str和bytes
str是unicode
1 #coding:utf-8 2 s='林' #当程序执行时,无需加u,'林'也会被以unicode形式保存新的内存空间中, 3 4 #s可以直接encode成任意编码格式 5 s.encode('utf-8') 6 s.encode('gbk') 7 8 print(type(s)) #<class 'str'>
bytes是bytes
1 #coding:utf-8 2 s='林' #当程序执行时,无需加u,'林'也会被以unicode形式保存新的内存空间中, 3 4 #s可以直接encode成任意编码格式 5 s1=s.encode('utf-8') 6 s2=s.encode('gbk') 7 8 9 10 print(s) #林 11 print(s1) #b'\xe6\x9e\x97' 在python3中,是什么就打印什么 12 print(s2) #b'\xc1\xd6' 同上 13 14 print(type(s)) #<class 'str'> 15 print(type(s1)) #<class 'bytes'> 16 print(type(s2)) #<class 'bytes'>
三、文件处理
1、文件操作的基本流程:
1 f = open('chenli.txt') #打开文件 2 first_line = f.readline() 3 print('first line:',first_line) #读一行 4 print('我是分隔线'.center(50,'-')) 5 data = f.read()# 读取剩下的所有内容,文件大时不要用 6 print(data) #打印读取内容 7 8 f.close() #关闭文件
2、文件打开模式
文件句柄 = open('文件路径', '模式')
打开文件的模式有:
- r ,只读模式【默认模式,文件必须存在,不存在则抛出异常】
- w,只写模式【不可读;不存在则创建;存在则清空内容,即覆盖】
- x, 只写模式【不可读;不存在则创建,存在则报错】
- a, 追加模式【可读; 不存在则创建;存在则只追加内容】
注:python中文件绝对路径写法:
f=open('D:\\python\\a.txt')
或者:
f=open(r'D:\python\a.txt')
"+" 表示可以同时读写某个文件
- r+, 读写【可读,可写】
- w+,写读【可读,可写】
- x+ ,写读【可读,可写】
- a+, 写读【可读,可写】
"b"表示以字节的方式操作
- rb 或 r+b
- wb 或 w+b
- xb 或 w+b
- ab 或 a+b
注:以b方式打开时,读取到的内容是字节类型,写入时也需要提供字节类型,不能指定编码
3、文件处理:控制指针到指定位置
read(3)代表读取3个字符,其余的文件内光标移动都是以字节为单位如seek,tell,read,truncate
seek 查找光标,每次默认从开始找
f.seek(3,0)
f.seek(3,1)当前位置
f.seek(3,2)末尾
4、上下文管理
为了避免打开文件后忘记关闭,可以通过管理上下文
即:
with open('log','r',encoding='utf-8') as f:
如此方式,当with代码块执行完毕时,内部会自动关闭并释放文件资源。
上下文管理应用实例:
修改a.txt文件内容
1 #上下文管理with 2 # read_f=open('a.txt','r',encoding='utf-8') 3 # write_f=open('.a.txt.swp','w',encoding='utf-8') 4 import os 5 with open('a.txt','r',encoding='utf-8') as read_f,\ 6 open('.a.txt.swp','w',encoding='utf-8') as write_f: 7 for line in read_f: 8 if 'alex' in line: 9 line=line.replace('alex','ALEXSB') 10 write_f.write(line) 11 os.remove('a.txt') 12 os.rename('.a.txt.swp','a.txt')
5、循环读取文件的方法
索引循环文件读取方法:先全部读取,存入内存,此方法占内存
循环文件读取方法:占用内存少
python中变量名全部大写当作常量
OLDBOY_AGE=57