文件处理
- 什么是文件?
- 操作系统提供给用户操作硬盘的一个工具
- 为什么要用文件?
- 因为人类和计算机要永久保存数据
- 怎么用文件?
f = open('a.txt', 'r', encoding='utf-8') #默认打开模式就为r
data = f.read() #调用文件对象下的读/写方法
print(data)
with的用法:
with open('a.txt', 'w') as f:
pass
#可以用with同事打开多个文件,用逗号分隔
with open('a.txt', 'r') as read_f, open('b.txt', 'w') as write_f:
data = read_f.read()
write_f.write(data)
一、文件操作模式
如果open函数中的encoding没有设置,默认是GBK,所以一般需要添加encoding参数
- r(默认):
- 只读
- 如果读的文件不存在,报错
with open('a.txt', 'r', encoding='utf-8') as f:
res = f.read()
- w:
- 只写
- 如果文件不存在,新建一个文件写入数据
- 如果文件存在且存在数据,会清空数据,重新写入
with open('a.txt', 'w', encoding='utf-8') as f:
f.write('hello!')
- a:
- 只追加写
- 如果文件不存在,新建一个文件写入数据
- 如果文件存在且存在数据,会在已有的数据后面追加写入数据
with open('a.txt', 'a', encoding='utf-8') as f:
f.write('
my name is Yang')
二、文件读写模式
前提:tb模式不能单独使用,必须与r/w/a之一结合使用
- t:文本模式
- 读写文件都是以字符串为单位的
- 只能针对文本文件
- 必须制定encoding参数
with open('a.txt', 'rt', encoding='utf-8') as f:
res = f.read()
print(type(res))
<class 'str'>
with open('a.txt', 'wt',encoding='utf-8') as f:
s = 'abc'
f.write(s) #写入也必须是字符串类型
- b:二进制模式
- 读写文件都是以bytes/二进制位单位的
- 可以针对所有文件
- 一定不能指定encoding参数
with open('1.png', 'rb') as f:
data = f.read()
print(type(data))
<class 'bytes'>
with open("a.txt", "wb") as f:
msg = 'hello'
res = msg.encode('utf-8') #res为bytes类型
f.write(res) #在b模式下写入文件的只能是bytes类型
三、操作文件的方法
- 读操作
f.read() #读取所有内容,执行完后,文件指针会移动到文件末尾
f.readline() #读取一行内容,光标移到到第二行首部
f.readlines() #读取每一行内容,存放于列表中
- 写操作
f.write('1111
2222
') #针对文本模式的写,需要自己写换行符
f.write('1111
2222
'.encode('utf-8')) #针对b模式的写,需要自己写换行符
f.writelines(['333/n', '444
']) #文件模式
f.writelines([bytes('333
', encoding='utf-8'), '444
'.encode('utf-8')])#b模式
f.readable() # 文件是否可读
f.writable() # 文件是否可写
f.closed # 文件是否关闭
f.encoding # 如果文件打开模式为b,则没有该属性
f.flush() #立刻将文件内容刷到硬盘
f.name
四、主动控制文件内指针移动
除了read里的参数,read(n),是针对字符的,其他的都是针对字节(Bytes)
with open('a.txt', 'r', encoding='utf-8') as f:
res = f.read(3) #读取3个字符
with open('a.txt', 'rb',)as f:
res = f.read(3) #读取3个bytes
-
若想要读取文件某一特定位置的数据,则需要f.seek方法主动控制文件内指针的移动:
-
f.seek(offset,whence)
- offset:相对偏移度(光标移动的位数)针对字节
- whence:指定光标位置从何开始
- 0:默认的模式,该模式代表指针移动的字节数是以文件开头为参照的
- 1:该模式代表指针移动的字节数是以当前所在的位置为参照的
- 2:该模式代表指针移动的字节数是以文件末尾的位置为参照的
-
0模式
with open('a.txt', 'r', encoding='utf8') as f:
f.seek(3, 0) #参照文件开头移动了3个字节
print(f.tell()) #查看当前文件指针距离文件开头的距离
print(f.read()) #从指针的后面读取到文件末尾
- 1模式
with open('a.txt', 'rb')as f:
f.seek(3, 1) #从当前位置往后移3个字节
print(f.tell())
f.seek(4, 1) #从移动了3个字节后的当前位置往后再移动4个字节
print(f.tell()) #所以这里的结果是 7
- 2模式
with open('a.txt', 'rb',)as f:
f.seek(0, 2) #参照文件末尾移动0个字节,即直接跳到文件末尾
print(f.tell())
f.seek(-3, 2) #参照文件末尾往前移动了3个字节
print(f.read().decode('utf8'))
五、文件的修改
方法一:将文件内容一次性全部读入内存,然后在内存中修改完毕后,再覆盖写回原文件
优先:在文件修改过程中同一份数据只有一份
缺点:会过多地占用内存
with open('a.txt', 'r', encoding='utf8')as f:
res = f.read()
with open('a.txt', 'w', encoding='utf8')as f:
data = f.write(res.replace('SB', 'this is a new inmanage'))
print(data)
方法二:以读的方式打开源文件,以写的方式打开一个临时文件,一行行读取源文件内容,修改完后写入临时文件,删掉源文件,将临时文件重命名为源文件名
优点:不会占用过多内存
缺点:在文件修改过程中同一份数据存了两份
import os
with open('a.txt', 'r', encoding='utf8')as read_f,
open('b.txt', 'w', encoding='utf8')as write_f:
for line in read_f:
write_f.write(line.replace('yes, ok ok', 'are you ok'))
os.remove('a.txt')
os.rename('b.txt', 'a.txt')