字符编码
运行python程序的三个步骤:
1.启动python解释器
2.解释器将test.pyde的内容从硬盘读入内存
3.解释器解释执行刚刚读入内存的代码,识别python语法。
第二个阶段:
怎么样避免乱码
用文本编辑器写文本文件时,要记得在开头注释(#codig:写入文件的字符编码表类型)
文件从硬盘把文件读入内存的的时候也用一样的字符编码表,这样可以避免乱码问题。
如果用python2需要在字符串前加u,x=u"上"这样会强制python2在存文件的时候把文件存成UTF-8的模式,python3不需要考虑乱码问题。
python2解释器将test.pyde的内容从硬盘读入内存默认用的ASCII编码表(ASCII只能读英文)
python3解释器默认用的UTF-8,不需要开头加"coding:"。unicode二进制永远不会乱码。
注意: 如果写入文件用的文本格式跟写入硬盘用的字符编码表不一致会导致数据丢失
bytes类型补充说明:
编码 编码
字符---------------》unicode-----------------------》其他编码
解码 解码
字符《---------------unicode《-----------------------其他编码
x = "上"
res = x.encode("gbk") # 编码格式,直接转成bytes格式
print(type(res)) # <class 'bytes'>
print(res) # b'\xc9\xcf'
在python3里只会将unicode格式的数字转成字符,其余编码格式均不会转换
print(res.decode("gbk")) #解码格式显示为直接转成字符 上
unicode一个英语字符对应一个字节,一个汉字对应2个字节
UTF-8一个英文对应一个字节,一个汉字对应3个字节
控制文件读写操作的模式
r 只读 (默认)
w 只写
a 只追加 往末尾写
控制文件读写内容的模式:
t 控制读写的内容都是字符串类型 (默认)
特点:1.只适用于文本文件
2.必须要指定encoding参数
b 控制读写的内存都是bytes类型
特点:1.一定不要指定encoding参数
r:如果文件不存在,则报错。如果文件存在则将文件指针跳到整个文件的开头
f = open(r"a.txt", mode="rt", encoding="utf-8")
print(f.read())
w:如果文件不存在,则创建空文档。如果文件存在,则清空,文件指针会跳到文件开头
f = open(r"b.txt", mode="wt", encoding="utf-8")
f.write("你好啊1\n")
f.write("你好啊2\n") # 打开文件不关的情况下,新写入的内容跟在老内容之后
f.write("你好啊3\n")
a.如果文件不存在,则创建空文档。如果文件存在,则文件指针会跳到文件末尾
f = open(r"c.txt", mode="at", encoding="utf-8")
f.write("你好啊1\n")
f.write("你好啊2\n")
f.write("你好啊3\n")
a模式跟w模式的差别:在关闭文件后,w模式写文件会清空文件,重新开始写。
a文件关闭文件后,不会清空文件内容。新写入的内容会跟在老内容之后
了解内容:
读写模式
r+t
w+t
a+t
例如:
f = open(r"c.txt", mode="r+t", encoding="utf-8")
print(f.readable()) # True
print(f.writable()) # True
print(f.read()) # 会显示原文内容
f.write("h") # 硬盘文件只有覆盖这一种,不能改原来文件
f.close()
b模式
with open("c.txt", mode="rb") as f:
res = f.read()
print(type(res)) # <class 'bytes'>
print(res) # 显示utf-8模式的2进制
print(res.decode("utf-8")) # 解码成字符串类型
t模式只能读文本文件,b模式可以读音频文件,图片文件
b模式可以是通用模式,可以解码文本文件,需要自己解码,也可以读音频文件还有图片
with open("c.txt", mode="wb")as f:
msg = "你好"
f.write(msg.encode("utf-8"))
这样写入文件等同于wt模式直接写入文件
读相关的模式
readlines
with open("a.txt", mode="rt", encoding="utf-8") as f:
res = f.read() # 直接全读入内存,文件如果过大,那么吃内存
print(res)
print("==============")
res=f.read()
print(res)
print(f.readline()) # 一次读一行,可以使用多次
print(f.readlines()) # 把文件所有的行读出来放在一个列表里,直接全读入内存
写相关的模式
writelines,flush
with open("a.txt", mode="wt", encoding="utf-8") as f:
f.write("111\n222\n333\n") # 可以写多行
lines = ["aaa\n", "bbb\n", "ccc\n"]
for line in lines:
f.write(line)
f.writelines(lines) # 跟上面代码的意思一样,把一个列表里面的值依次写入一个文本文件
f.writelines("hello") # hello
f.write("hello") # hello
两个功能的差别:writelines 写了5次 write写了一次
f.write("hello")
f.flush() # flush是提示操作系统把内存数据每写一条就读入硬盘
原理,write写的程序先存入内存,由内存存一段时间存入硬盘,flush是提示操作系统把内存
数据每写一条就读入硬盘,是一种降低效率的io操作.
print(f.closed) # 判断文件有没有关闭
print(f.name) # 显示文件名字
拷贝文件
witn open("1.mp4",mode="rb") as scr_f,open(r"D\2.mp4",mode"wb") as dst_f:
dst_f.write(src_f.read()) # 把文件一次性全部读入内存,再写入dst_f文件中
解决内存空间问题,一行一行读代码,读一行写一行
for line in scr_f:
dst_f.write(line)
只有t模式下的read(n)的n代表的是字符个数,除此以外都是字节个数
with open("a.txt", mode="rt", encoding="utf-8") as f:
res = f.read(6) # 读出6个字符
print(res)
with open("a.txt", mode="rb")as f:
res = f.read(8) # 读出8个字节
print(res)
print((res.decode("utf-8"))) # 解码成utf-8的模式
截断,把文件的内容按照字节截断,删除文件指定字节后面的内容
with open("a.txt",mode="at",encoding="utf-8")as f:
f.truncate(6) # 保留6个字节,删除6个字节后面的内容
主动控制指针移动
f.seek(移动的字节个数,模式)
模式有三种:
0:永远参照文件开头
1:参照当前所在位置
2:永远参照文件末尾
注意:0模式可以在t下使用,也可以在b模式下使用,但是1和2只能在b模式下使用,不可以在t模式下使用。
with open("a.txt", mode="rt",encoding="utf-8") as f:
f.seek(3,0) # 把指针从开头向后移动了三个字节
print(f.read()) # print后会把剩下的文件内容读出来
f.seek(5,0) # 把指针从开头向后移动了5个字节
print(f.tell()) # tell显示距离文件开头有多少字节
with open("a.txt", mode="rb") as f:
f.seek(3,1) # b模式下刚开始打开文件指针在开头
f.seek(5, 1) # 1相对移动动,上一行先移动了3,这一次移动了5个字节,一共移动了8个字节
print(f.tell()) # tell显示距离文件开头有多少字节
res=f.read() # 这个read读出的是字节模式
print(res.decode("utf-8")) # decode把字节解码成字符
with open("a.txt", mode="rb") as f:
f.seek(-3,2) #2 模式永远参照文件末尾,文件末尾是没有文件内容的,所以一般都是倒过来从末尾移动到文件内容
print(f.tell())
f.seek(0, 2) # 指针直接跳到文件末尾
动态监测文件最后一行追加的内容
原理:
1.创建一个文件access.log负责接收文件的内容
2.把access的”遥控手柄“给到nana.py,nana.py负责往文件里面写内容:
import time
print(time.strftime("%Y-%m-%d %H:%M:%S")) # 导入时间模块,拼接出现在的时间
with open("access.log",mode="at",encoding="utf-8")as f:
f.write("%s %s\n"%(time.strftime("%Y-%m-%d %H:%M:%S"),"娜娜今天想了我100次"))
3.再创建一个文件tell.py负责监测文件access.log的内容
import time
with open("access.log", mode="rb")as f:
f.seek(0, 2) # 用于参照文件末尾
while True:
line = f.readline()
if len(line) == 0:
time.sleep(0.1)
else:
print(line.decode("utf-8"), end=" ") # end = ""取消print自带的换行符
文件修改的两种方式:
方法1:(这种方法一次性把文件内容全部读入新文件,比较耗内存,但是不耗硬盘)
1.将文件内容完全读入内存
2.将内存中完成修改
3.将修改后的文件覆盖回原文件
with open("e.txt", mode="rt", encoding="utf-8")as f:
data = f.read()
with open("e.txt", mode="wt", encoding="utf-8")as f1:
f1.write(data.replace("EGON", "egon"))
方法2:(这种方法比较节省内存空间,文件每次读入一行,新文件就改一行,但是文件全部写完时,硬盘里面相当于有两个文件,所以这种方式比较耗硬盘)
1.以读的方式打开原文件,然后在以写的方式打开一个临时文件
2.读原文件的一行内容到内存,然后在内存中修改完毕后再写入临时文件,循环往复直到全部写完
3.删除原文件,将临时文件重命名为原文件
import os #导入一个os模块
with open("e.txt", mode="rt", encoding="utf-8")as src_f, open(".e.txt.swp", mode="wt", encoding="utf_8")as dst_f:
for line in src_f:
dst_f.write(line.replace("egon", "EGON"))
os.remove("e.txt") #删除原文件 e.txt
os.rename(".e.txt.swp", "e.txt") #将新文件名字.e.txt.swp改成e.txt
运维注意事项:
类似vrm编辑器,word编辑器这种文本编辑器都是一次性把文件内容全部读出来的,
所以我们以后在用这些编辑器看一些比较大的文件的时候,要切记不要用这种编辑器看文件,
因为这种打开文件的方式非常吃内存。