文件操作
目录
一.前言
- 什么是文件?
文件是操作系统暴露给用户操作硬盘的快捷方式
内存中存放的数据在计算机关机后就会消失。要长久保存数据,就要使用硬盘、光盘、U 盘等设备。
应用程序若想操作硬件必须通过操作系统,而文件就是操作系统提供给应用程序来操作硬盘的虚拟概念,用户或应用程序对文件的操作,就是向操作系统发起调用,然后由操作系统完成对硬盘的具体操作。
二.在python中打开/关闭文件
open方法
open()
返回一个文件对象,最常使用的是两个位置参数和一个关键字参数:
open(filename, mode, encoding=None)
# 1.使用open函数,相当于python解释器跟操作系统说我要打开a.txt文件,操作系统找到a.txt在硬盘中存放的位置,打开a.txt,占用一定资源,再返回一个文件对象,通过操作这个文件对象,我们就可以操作硬盘中的文件了。我们用变量名f跟这个文件对象绑定,方便调用。
f = open('a.txt','r',encoding='utf-8') # 以 r模式 utf-8解码 打开硬盘中的 a.txt文件
# 2. 调用文件对象下的读/写方法,会被操作系统转换为读/写硬盘的操作
print(f.read()) # read是文件对象的内置方法
# 3.向操作系统发起关闭文件的请求,回收系统资源
f.close() # 告诉操作系统 这个文件我不用了 操作系统会将f对应的文件关闭
close资源回收
打开一个文件包含两部分资源:python解释器中的变量f和操作系统打开的文件。
f.close()
关掉操作系统打开的文件del f
删除变量f
f = open('data.txt', 'r', encoding='utf8')
f.close()
print(f) # <_io.TextIOWrapper name='data.txt' mode='r' encoding='utf8'>
print(f.read()) # ValueError: I/O operation on closed file. # f.close之后无法再使用这个文件,因为操作系统已经把文件关了
del f # 删除变量名f python垃圾回收机制也会帮助我们做这件事
请注意:f.close()
是必须的,如果不关闭,这个文件就会一直在打开的状态,占用资源。del f
一定要发生在f.close()
之后,否则也会导致操作系统打开的文件无法关闭。
with上下文管理 (推荐使用)
python中提供with
关键字供我们进行资源回收管理。with
的子句体结束后,即便触发异常,文件也可以正常关闭。
# 1、在执行完子代码块后,with 会自动执行f.close()
with open('a.txt','w') as f:
print(f.closed) # False # f.closed查看文件是否关闭
print(f.closed) # True
# 2、可用用with同时打开多个文件,用逗号分隔开即可
with open('a.txt','r') as read_f,open('b.txt','w') as write_f:
data = read_f.read()
write_f.write(data)
三.文件的操作模式
r模式的使用
# 1.路径中没有指定的文件 会直接报错 文件存在时,文件内指针直接跳到文件开头
with open('a.txt', 'r', encoding='utf-8') as f :
pass # FileNotFoundError: [Errno 2] No such file or directory: 'a.txt'
# 2.只能读不能写
with open('a.txt', 'r', encoding='utf-8') as f :
f.write('hello') # io.UnsupportedOperation: not writable
# 3.读一下文件吧
with open('a.txt','r',encoding='utf-8') as f:
data = f.read() # 会将文件的内容由硬盘全部读入内存,赋值给data
w模式的使用
# 1.路径中没有指定的文件时 会创建一个新文件 文件存在会清空文件 文件指针跑到文件开头
with open('b.txt',mode='w',encoding='utf-8') as f:
f.write('hello')
f.write('world') # helloworld
# 在文件不关闭的情况下,连续的写入,后写的内容一定紧跟在前写内容的后面
with open('b.txt',mode='w',encoding='utf-8') as f: # 再次打开b.txt
f.write('hi') # 此时文件中的内容会变成hi
# 2.只写模式不能读
# 会报错:io.UnsupportedOperation: not readable
a模式的使用
# 1.a可记为append 当文件存在时 他会直接接着后面写入 文件不存在时 也会创建一个新文件
with open('c.txt',mode='a',encoding='utf-8') as f:
f.write('hello')
# a模式不会清空文件内容 他会把光标移动到文件末尾 然后开始进行写的操作 a模式也是只能写不能读
+模式的使用
# r+ w+ a+ :可读可写
# 在平时工作中,我们只单纯使用r/w/a,要么只读,要么只写,一般不用可读可写的模式
b模式的使用 (重要)
# 模式的使用 b模式是二进制模式 所有的图片视频音频都只能使用该模式
with open('img.png', 'rb') as f: # 使用二进制只读模式rb 打开一张图片
data = f.read()
print(data) # b'\x89PNG\r\n\x1a\n\x00\x00\x00\r.... # bytes类型的数据
print(type(data)) # <class 'bytes'> 可看成二进制
操作文件的方法
读文件
# 1.使用for循环
with open('a.txt', mode='rt', encoding='utf-8') as f:
for line in f:
print(line, end='') # 同一时刻只读入一行内容到内存中
# 结果会出现很多的换行符 因为每行末尾都会有一个看不见的换行符 print也会自带一个换行符
# 可使用line.rstrip # print(line.rstrip('\n'))
# 2.使用read(1024)
with open('img.png',mode='rb') as f:
while True:
data=f.read(1024) # 同一时刻只读入1024个Bytes到内存中
if len(data) == 0:
break
print(data)
写文件
额外的方法
f.readable() # 文件是否可读
f.writable() # 文件是否可读
f.closed # 文件是否关闭
f.encoding # 如果文件打开模式为b,则没有该属性
f.flush() # 立刻将文件内容从内存刷到硬盘 相当于ctrl+s
控制文件内光标的移动
seek方法
# 1.创建文件
with open('test.txt', mode='wt', encoding='utf8') as f:
f.write('abc你好')
# 2.以0模式移动光标
with open('test.txt', mode='rt', encoding='utf8') as f:
f.seek(3, 0) # 参照文件开头移动了3个字节 0模式
print(f.tell()) # 查看当前文件指针距离文件开头的位置,输出结果为3
print(f.read()) # 从第3个字节的位置读到文件末尾,输出结果为:你好
# 注意:由于在t模式下,会将读取的内容自动解码,所以必须保证读取的内容是一个完整中文数据,否则解码失败
# 3.以二进制模式打开
with open('test.txt', mode='rb') as f:
f.seek(6, 0) # 0表示:0模式
print(f.read().decode('utf-8')) # 输出结果为: 好 # 二进制模式所以要解码
# 4.以1模式 从当前位置
with open('test.txt', mode='rb') as f: # abc3个字节 你好6个字节
print(f.read().decode('utf8')) # read之后光标会移动到末端
f.seek(0)
f.seek(3, 1) # 从当前位置往后移动3个字节,而此时的当前位置就是文件开头
print(f.tell()) # 输出结果为:3
f.seek(4, 1) # 从当前位置往后移动4个字节,当前位置为3
print(f.tell()) # 输出结果为:7
# print(f.read().decode('utf8')) # 会报错 因为光标(7)卡在汉字的三个字节之间 相当于数据不是完整的 导致汉字无法解码
# 5.以2模式 从末尾
with open('test.txt',mode='rb') as f:
print(f.tell()) #文件刚打开光标还是在开头 但是seek会从末尾开始移动 seek(0)代表末尾
f.seek(0,2) # 参照文件末尾移动0个字节, 即直接跳到文件末尾
print(f.tell()) # 输出结果为:9
f.seek(-3,2) # 参照文件末尾往前移动了3个字节 刚好移动到‘好’这个字前面
print(f.read().decode('utf-8')) # 输出结果为:好
t模式下的read是以字符为单位(了解)
# 大前提:文件内指针的移动都是Bytes为单位的,唯一例外的是t模式下的read(n),n以字符为单位
with open('test.txt', mode='rt', encoding='utf-8') as f:
data = f.read() # 读取4个字符
print(data,type(data)) # abc你 <class 'str'>
#
with open('test.txt', mode='rb') as f:
data = f.read(6) # 读取6个Bytes
print(data.decode('utf8'),type(data)) # abc你 <class 'bytes'>
文件内容的修改(了解)
# 修改文件内容的方式1:覆盖写
# with open(r'a.txt', 'r', encoding='utf8') as f:
# data = f.read()
# with open(r'a.txt', 'w', encoding='utf8') as f1:
# f1.write(data.replace('jason', 'tony'))
# 修改文件内容的方式2:换地写
'''先在另外一个地方写入内容 然后将源文件删除 将新文件命名成源文件'''
import os
with open('a.txt', 'r', encoding='utf8') as read_f, \
open('.a.txt.swap', 'w', encoding='utf-8') as write_f:
for line in read_f:
write_f.write(line.replace('tony', 'kevinSB'))
os.remove('a.txt') # 删除a.txt
os.rename('.a.txt.swap', 'a.txt') # 重命名文件