1.b模式
控制文件读写内容的模式
t模式:
1.读写都是字符串(Unicode)为单位
2.只能针对文本文件
3.必须指定字符编码 即必须指定encoding='utf-8'
b 模式:binary模式 通用所有文件
1.读写都是以bytes为单位
2.可以针对所有文件
3.一定不能指定字符编码 即不能指定encoding='utf-8'
放一张图片tubiao.png到当前目录下,以b模式下,对图片文件进行操作
with open(r'tubiao.png',mode='rb') as f:
res=f.read()
print(res)
print(type(res))
# b'\x89PNG\r\n\x1a\……
#<class 'bytes'>
循环读取文件方式:
方式1:控制每次读取字节数量
with open(r'tubiao.png',mode='rb') as f:
while True:
res=f.read(1024)
if len(res)==0:
break
print(res)
print(len(res))
方式2:每次读取一行数据,
当一行内容过多时,容易一次性读取数据量过大
with open(r'tubiao.png',mode='rb') as f:
for line in f:
print(line)
b模式案例:针对所有文件类型的拷贝工具
src_file=input('被拷贝的文件路径>>>').strip()
new_src_file=input('拷贝后的文件路径>>>').strip()
with open(r'{}'.format(src_file),mode='rb') as f1,\
open(r'{}'.format(new_src_file),mode='wb') as f2:
# res=f1.read()#内存占用过大
# f2.write(res)
for line in f1:
f2.write(line)
2.文件操作的其他方法
readline 一次读一行
with open(r'db',mode='rt',encoding='utf-8') as f:
res1=f.readline()
res2=f.readline()
print(res1,res2)
# blll: fsdf
# dfsdf: fsdf
readlines 一次读出整个文件,并将每一行做一个元素组成列表
with open(r'db',mode='rt',encoding='utf-8') as f:
res=f.readlines()
print(res)
# ['blll:fsdf\n', 'dfsdf:fsdf\n']
read和readlines都是一次将整个文件从硬盘导入内存,谨慎之用。
其余还有一些仅需了解,不常使用的操作方法,不做记录。
3.操作文件指针移动
指针移动的单位都是bytes字节,只有在t模式下的read(n) n代表的单位是字符,一个英文字符一个字节 一个中文字符三个字节。
with open(r'aaa.txt',mode='rt',encoding='utf-8') as f:
res=f.read(4)
print(res) #aaa你 读出了前四个字符
1. f.seek(n,模式):
n指移动的字节个数
模式1:0 以文件开头为参照原点
f.seek(9,0)
f.seek(3,0) #3
只有0模式可以在t模式下使用1、2都要在b模式下使用
#示范 0模式
with open(r'aaa.txt',mode='rb') as f:
f.seek(3,0)
print(f.tell())
res=f.read()
print(res.decode('utf-8'))
f.seek(4, 0)
print(f.tell())
res = f.read()
print(res.decode('utf-8'))
#因为一个汉字占三个字节,如果从中间切割是没办法编码的,会报错
#UnicodeDecodeError: 'utf-8' codec
# can't decode byte 0xbd in position 0: invalid start byte
模式2:1 以文件当前位置为参照原点
f.seek(9,1)
f.seek(3,1)#12
#示范 1模式
with open(r'aaa.txt',mode='rb') as f:
f.seek(9, 1)
f.seek(3,1)
print(f.tell())#12
res=f.read()
print(res.decode('utf-8'))#空
模式3:2 以文件末尾为参照原点,应该倒着移动
f.seek(-9,2) #3
f.seek(-3,2) #9
#示范 2模式
with open(r'aaa.txt',mode='rb') as f:
f.seek(-9, 2)
f.seek(-3,2)
print(f.tell())#6
res=f.read()
print(res.decode('utf-8'))#好
控制指针并不是很常用
2.f.seek()应用案例
模仿Linux的捕捉文件末尾增加内容命令 tail -f access.log (access.log是要监测的文件)
1.目录下新建日志文件access.log
2.实现监测日志文件access.log 的新增内容 的程序代码
#监测日志文件access.log 的新增内容
import time
with open(r'access.log',mode='rb') as f:
#1.将指针跳到文件末尾
f.seek(0,2)
while True:
line=f.readline()
if len(line)==0:
time.sleep(0.3)
else:
print(line.decode('utf-8'))
3.新建一个追加日志内容的程序:
with open(r'access.log',mode='at',encoding='utf-8') as f:
f.write('2021-7-13 bob转账100万给amy\n')
运行2,再运行3,每运行一次3,新增的内容都会被监测程序打印出来。
4.文件修改的两种方式
对于硬盘来说,压根就没有“改”这个功能,都是用新内容完全覆盖旧内容
不要同一行代码,以读(r)的方式打开文件,又以写(w)的方式打开文件,因为那样会直接把文件清空掉。
在当前目录下新建文本文件c.txt,随便添加一些内容,用于演示
方式1:文本编辑器用的就是这种方式
with open(r'c.txt',mode='rt',encoding='utf-8') as f:
res=f.read()
data=res.replace('哈哈','呵呵')
print(data)
# 娃呵呵
# 娃呵呵
# 娃呵呵
with open(r'c.txt',mode='wt',encoding='utf-8') as f:
f.write(data)
方式2:避免了从硬盘读入内存数据量过大
import os
with open(r'c.txt',mode='rt',encoding='utf-8') as f,\
open(r'c111.txt',mode='wt',encoding='utf-8') as f1:
for line in f:
f1.write(line.replace('呵呵','哈哈'))
os.remove('c.txt')
os.rename('c111.txt','c.txt')
方式1占内存,方式2占硬盘