文件处理
一、文件操作流程
什么是文件?
文件是操作系统提供给应用程序来操作硬盘的一个工具,用户或应用程序对文件的操作,就是向操作系统发起调用,然后由操作系统完成对硬盘的具体操作
为什么要用文件?
需要永久保存数据
基本流程
1、打开文件,由应用程序向操作系统发起系统调用open(),操作系统打开该文件,对应一块硬盘空间,并返回一个文件对象赋值给变量f
f = open('文件路径','打开文件的模式','编码')
# 文件路径可以是相对路径,也可以是绝对路径
# 默认打开方式就是r
# 指定打开字符编码,什么方式存,就以什么方式打开
2、调用文件对象下的读/写方法,会被操作系统转换为读/写硬盘操作
data = f.read()
3、向操作系统发起关闭文件的请求,回收资源
f.close()
在操作完一个文件后,必须把与该文件有关的资源全部回收,变量资源python可以自动回收,但是操作系统打开的文件资源不能自动关闭,这就需要close()方法来关闭,还有另外一种方式打开文件,会自动执行close():
# 打开一个文件 with open('a.txt','r',encoding='utf-8')as f: pass # 可以同时打开多个文件 with open('a.txt','r',encoding='utf-8')as rf, \ open('a.txt','w',encoding='utf-8')as wf: print(rf.read()) wf.write('123')
二、文件操作模式
1、文件打开模式
r:只读:
1、只能读,不能写
2、如果文件不存在的话,就会报错
# 判断文件是否可读 with open('test.txt', 'r', encoding='utf-8')as f: print(f.readable()) # 读取文件全部内容 with open('test.txt', 'r', encoding='utf-8')as f: data = f.read() print(data) # 循环读取文件中每行的内容 with open('test.txt', 'r', encoding='utf-8')as f: for line in f: print(line) # readline() 每次读取一行内容 with open('test.txt', 'r', encoding='utf-8')as f: print(f.readline()) print(f.readline()) print(f.readline()) print(f.readline()) # readlines() 将数据全部读入内存,以换行符分隔,存入列表 with open('test.txt', 'r', encoding='utf-8')as f: line = f.readlines() print(line)
w:只写:
1、只能写,不能读
2、如果文件不存在的话,会创建新文件
3、如果文件存在的话,先清空源文件,再写入新文件
with open('test.txt', 'w', encoding='utf-8')as f: print(f.writable()) f.write('123') f.write('111') f.write('123')
a:追加写:
1、只能写,不能读
2、如果文件不存在的话,会创建新文件
3、如果文件存在的话,会在原数据的末尾追加新数据
with open('test.txt', 'a', encoding='utf-8')as f: f.write('aaa')
r+、w+、a+:可读可写
2、文件处理模式
t 模式:如果我们指定文件打开模式为r/w/a,其实默认就是rt/wt/at
t 模式只能用于操作文本文件,无论读写,都应以字符串为单位
b 模式:读写都是以二进制
with open('test.txt', 'rb')as f: res = f.read() print(type(res)) # 输出结果为:<class 'bytes'> with open('test.txt', 'wb')as f: msg = '你好' res = msg.encode('utf-8') # res为bytes类型 f.write(res) # 在b模式下写入文件的只能是bytes类型
在操作纯文本文件方面t模式帮我们省去了编码与解码的过程,b模式则需要手动编码与解码,所以此时t更方便
针对非文本文件(如图片、音频、视频)只能使用b模式
三、文件内光标移动
文件内指针的移动都是bytes为单位的,唯一例外的是t模式下的read(n),n是以字符为单位的
with open('test.txt', 'r')as f: data = f.read(3) # 读取3个字符 with open('test.txt', 'rb')as f: data = f.read(3) # 读取3个bytes
seek方法:
seek有两个参数:seek(offset,whence)
offset:相对偏移度 (光标移动的位数)针对的是字节
whence:指定光标位置从何开始
0:从文件开头
1:从当前位置
2:从文件末尾
其中o模式可以在t或者b模式下使用,而1和2模式只能在b模式下用
补充:utf-8:英文是1个bytes,中文是三个bytes
gbk:全部是2个bytes
o模式
with open(r"test.txt", 'r')as f: # 打开文件的编码:gbk print(f.read(6)) print(f.tell()) f.seek(8, 0) print(f.read(2)) print(f.read(5)) with open(r"test.txt", 'rt', encoding='utf-8')as f: # 打开文件的编码:gbk print(f.read()) f.seek(6, 0) print(f.tell()) print(f.read(2))
1模式
with open(r'test.txt', 'rb')as f: print(f.read(10).decode('gbk')) f.seek(10, 1) print(f.tell())
2模式
with open(r'test.txt', 'rb')as f: f.read() print(f.tell()) f.seek(-3, 2) print(f.tell())
四、文件的修改
1、将文件内容一次性全部读入内存中,然后在内存中修改完毕后再覆盖写回原文件
# 将文件中的“这个”替换成“你好” with open(r'test.txt', 'r', encoding='gbk')as f: data = f.read() print(data) with open(r'test.txt', 'w', encoding='gbk')as f: res = data.replace('这个', '你好') f.write(res)
优点:在文件修改过程中同一份数据只有一份
缺点:会过多地占用内存
2、以读的方式打开原文件,以写的方式打开另外一个临时文件,一行行读取原文件内容,修改后写入临时文件,删除原文件,将临时文件重命名原文件名
import os with open(r'test.txt', 'r', encoding='utf-8')as rf,\ open(r'test_wap.txt', 'w', encoding='utf-8')as wf: for line in rf: wf.write(line.replace('这个', '你好')) os.remove('test.txt') os.rename('test_wap.txt', 'test.txt')
优点:不会占用过多地内存
缺点:在文件修改过程中,同一份数据存了两份