文件的相关操作
初识文件操作
使用python操作一个文件需要的必要参数有:
文件路径:比如 "C:\Users\Ethan\Desktop\新建文本文档.txt"
编码方式:比如 gbk, utf-8等
操作模式:只读,只写,追加,写读,读写等
计算机系统分为:计算机硬件,操作系统,应用程序三部分。
我们用python或其他语言编写的应用程序若想要把数据永久保存下来,必须要保存于硬盘中,这就涉及到应用程序要操作硬件,众所周知,应用程序是无法直接操作硬件的,这就用到了操作系统。操作系统把复杂的硬件操作封装成简单的接口给用户/应用程序使用,其中文件就是操作系统提供给应用程序来操作硬盘虚拟概念,用户或应用程序通过操作文件,可以将自己的数据永久保存下来
f = open(r"C:\Users\Ethan\Desktop\新建文本文档.txt", mode = "r", encoding = "utf-8") content = f.read() print(content) f.close()
结果:
MVC
OSI
谈谈人工智能
对象调用
f: 变量,一般都写成 f, f_obj, file, f_handler, fh 等,通常称作文件句柄,对文件进行的任何操作,都得通过文件句柄.进行 open: 内置函数,open底层调用的是操作系统的接口 mode: 定义的操作模式,r为读模式 encoding(可以写或者不写):不是具体的编码或者解码,他就是声明:此次打开文件使用什么编码本,一般来说:你的文件用什么编码方式保存的,就用什么方式打开。 在不写情况下,默认编码本:操作系统的默认编码 windows:gbk linux:utf-8 mac: utf-8 close(): 关闭文件句柄(可以把文件句柄理解成一个空间,这个空间存在内存中,必须要主动关闭)
文件操作三部曲:
1. 打开文件
2. 对文件句柄进行相应操作
3. 关闭文件
常见报错
1. 路径问题
比如遇到:OSError: [Errno 22] Invalid argument: 'D:\\SemEval2019\\SemEval2019_result\task6'
解决方法1:
多加一个\,例如将 "C:\Users\Ethan\Desktop\新建文本文档.txt", mode = "r", encoding = "utf-8" ---> "C:\\Users\Ethan\Desktop\新建文本文档.txt", mode = "r", encoding = "utf-8"
解决方法2:
路径前面添加 r, 例如 r"C:\Users\Ethan\Desktop\新建文本文档.txt", mode = "r", encoding = "utf-8"
相对路径与绝对路径:
1.绝对路径:从磁盘根目录开始一直到文件名
2.相对路径:用一个文件夹下的文件,相对于当前这个程序所在的文件而言.如果在同一个文件中,则相对路劲就是这个文件名.如果再上一层文件夹则要使用 ../ 相对路径下,你就可以直接写文件名即可。
2. 编码问题
这个问题就是你打开文件的编码与文件存储时的编码用的编码本不一致导致的
解决方法: 将 gbk 更改成 utf-8 等
文件操作:读
r, rb,r+,r+b
r 模式:
以只读方式打开文件,文件的指针将会放在文件的开头。是文件操作最常用的模式,也是默认模式,如果一个文件不设置mode,那么默认使用r模式操作文件。
read() 将文件中的内容全部读取出来; 弊端:如果文件很大就会非常的占用内存,容易导致内存奔溃
f = open("trial", mode = "r", encoding = "utf-8") # mode可以不写,默认为 r content = f.read() print(content) f.close() 结果: ab高频考点特征图 图形推理必做题 拆分定义判断解题 逻辑论证题 传统文化类类比推理
read(n) 读取的时候指定读取到什么位置 在r模式下,读取n个字符。
# f = open("trial", encoding = "utf-8") # msg1 = f.read(4) # print(msg1) # ab高频 # f.close() f = open("trial", encoding = "utf-8") msg1 = f.read(4) msg2 = f.read() print(msg1) # ab高频 print("**************") print(msg2) f.close() 结果: ab高频 ************** 考点特征图 图形推理必做题 拆分定义判断解题 逻辑论证题 传统文化类类比推理
readline() 每次只读取一行, 注意点:readline()读取出来的数据在后面都有一个\n
# f = open("trial", encoding = "utf-8") # msg1 = f.readline() # print(msg1) # ab高频考点特征图 # f.close() f = open("trial", encoding = "utf-8") msg1 = f.readline() msg2 = f.readline() msg3 = f.readline() msg4 = f.readline() print(msg1) print(msg2) print(msg3) print(msg4) f.close() 结果: ab高频考点特征图 图形推理必做题 拆分定义判断解题 逻辑论证题 f = open("trial", encoding = "utf-8") msg1 = f.readline().strip() msg2 = f.readline().strip() msg3 = f.readline().strip() msg4 = f.readline().strip() print(msg1) print(msg2) print(msg3) print(msg4) f.close() 结果: ab高频考点特征图 图形推理必做题 拆分定义判断解题 逻辑论证题
readlines() 返回一个列表,列表里面每个元素是原文件的每一行,如果文件很大,占内存,容易崩盘。
# f = open("trial", mode = "r", encoding = "utf-8") # mode可以不写,默认为 r # content = f.readlines() # print(content) # ['ab高频考点特征图\n', '图形推理必做题\n', '拆分定义判断解题\n', '逻辑论证题\n', '传统文化类类比推理'] # f.close() f = open("trial", mode = "r", encoding = "utf-8") # mode可以不写,默认为 r content = f.readlines() for cont in content: print(cont.strip()) f.close() 结果: ab高频考点特征图 图形推理必做题 拆分定义判断解题 逻辑论证题 传统文化类类比推理
for 通过for循环去读取文件,文件句柄是一个迭代器,他的特点就是每次循环只在内存中占一行的数据,非常节省内存。
f = open("trial", encoding = "utf-8") for line in f: print(line.strip()) f.close() 结果: ab高频考点特征图 图形推理必做题 拆分定义判断解题 逻辑论证题 传统文化类类比推理
rb 模式
rb 操作的是非文字的文件,比如图片,视频,音频等。 它以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。带b的都是以二进制的格式操作文件。 带有b的模式操作文件,那么不用声明编码方式 rb模式也有read read(n) readline(),readlines() for循环这几种方法
f = open("1.jpg", mode = "rb") msg = f.read() print(msg) # b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00\xff\xdb\x00C\x00\n\t\n\x0b\ f.close()
文件的操作:写
w,wb,w+,w+b
w 模式
没有文件,创建文件,写入内容
# f = open("文件的写", encoding = "utf-8", mode = "w") # f.write("随便写一点") # f.close() # f = open("文件的写一写", encoding = "utf-8", mode = "w") # f.writelines("近期,香港暴发第三拨新冠肺炎疫情\n,连续多日确诊病例过百。许多香港市民停工、失业,生命健康受到严重威胁\n,原本受到黑暴冲击的香港经济雪上加霜。") # f.close()
如果文件存在,先清空源文件内容,再写入新内容
# f = open("文件的写", encoding = "utf-8", mode = "w") # f.write("好嗨哦") # f.flush() # 强制保存 # f.close()
wb 模式
以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如:图片,音频,视频等。
# 先以二进制方式打开1.jpg读取出内容,再写进 f = open("1.jpg", mode = "rb") msg = f.read() f.close() f1 = open("2.jpg", mode = "wb") f1.write(msg) f1.close()
文件的操作:追加
a, ab, a+ ,a+b
a 模式
打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
没有文件则创建文件,追加内容
# f = open("文件的追加", encoding = "utf-8", mode = "a") # f.write("息息相关") # f.close()
有文件,则在源文件的最后面追加内容
f = open("文件的追加", encoding = "utf-8", mode = "a") f.write("百年老窖") f.close()
文件操作的其他模式
+就是加一个功能。r+ 读写模式,w+ 写读模式,a+ 写读模式,r+b 以bytes类型的读写模式.........
#1. 打开文件的模式有(默认为文本模式): r ,只读模式【默认模式,文件必须存在,不存在则抛出异常】 w,只写模式【不可读;不存在则创建;存在则清空内容】 a, 只追加写模式【不可读;不存在则创建;存在则只追加内容】 #2. 对于非文本文件,我们只能使用b模式,"b"表示以字节的方式操作(而所有文件也都是以字节的形式存储的,使用这种模式无需考虑文本文件的字符编码、图片文件的jgp格式、视频文件的avi格式) rb wb ab 注:以b方式打开时,读取到的内容是字节类型,写入时也需要提供字节类型,不能指定编码 #3,‘+’模式(就是增加了一个功能) r+, 读写【可读,可写】 w+,写读【可写,可读】 a+, 写读【可写,可读】 #4,以bytes类型操作的读写,写读,写读模式 r+b, 读写【可读,可写】 w+b,写读【可写,可读】 a+b, 写读【可写,可读】
r+ 模式
r+: 打开一个文件用于读写。文件指针默认将会放在文件的开头。
# r+ 读写:读并追加 文件必须要先存在,否则报错 # f = open("文件的读写", encoding = "utf-8", mode = "r+") # msg = f.read() # print(msg) # f.write("人的一切痛苦,本质都是对自己无能的愤怒") # f.close()
注意:如果你在读写模式下,先写后读,那么文件就会出问题,因为默认光标是在文件的最开始,你要是先写,则写入的内容会讲原内容覆盖掉,直到覆盖到你写完的内容,然后在后面开始读取。
# 错误示例 f = open("文件的读写1", encoding = "utf-8", mode = "r+") f.write("人的一切痛苦,本质都是对自己无能的愤怒") msg = f.read() print(msg) f.close()
文件操作的其他功能
read(n)
1. 文件打开方式为文本模式时,代表读取n个字符
2. 文件打开方式为b模式时,代表读取n个字节
seek()
seek(n)光标移动到n位置, 移动单位是byte,所有如果是utf-8的中文部分则是3的倍数
通常我们使用seek都是移动到开头或者结尾
移动到开头:seek(0)
移动到结尾:seek(0,2) seek的第二个参数表示的是从哪个位置进行偏移,默认是0,表示开头,1表示当前位置,2表示结尾
# f = open("文件其他功能", encoding = "utf-8", mode = "r+") # f.seek(0) # 光标移动到开头 # msg = f.read() # 读取内容, 此时光标移动到结尾 # print(msg) # f.seek(0) # 再次将光标移动到开头 # f.seek(0, 2) # 将光标移动到结尾 # msg1 = f.read() # 读取内容. 什么都没有 # print(msg1) # f.seek(0) # 移动到开头 # f.write("刘德华") # f.close() # f = open("文件其他功能1", encoding = "utf-8") # f.seek(9) # msg = f.read() # print(msg) # f.close()
tell()
获取当前光标在什么位置, 单位字节
# f = open("文件其他功能", mode = "r+", encoding = "utf-8") # f.seek(0) # 光标移动到开头 # content = f.read() # 读取内容, 此时光标移动到结尾 # print(content) # f.seek(0) # 再次将光标移动到开头 # f.seek(0, 2) # 将光标移动到结尾 # content2 = f.read() # 读取内容. 什么都没有 # print(content2) # f.seek(0) # 移动到开头 # f.write("张国荣") # 写入信息. 此时光标在9 中⽂文3 * 3个 = 9 # print(f.tell()) # 光标位置9 # f.flush() # f.close() # f = open("文件其他功能1", encoding = "utf-8") # print(f.tell()) # msg = f.read() # print(f.tell()) # f.close() # flush 强制刷新 f = open("文件其他功能1", encoding = "utf-8", mode = "w") f.write("王者荣耀坑人") f.flush() f.close()
readable(),writeable()
f = open('Test',encoding='utf-8',mode='r') print(f.readable()) # True print(f.writable()) # False content = f.read() f.close()
打开文件的另一种方式
#1,利用with上下文管理这种方式,它会自动关闭文件句柄。 with open("trial", encoding = "utf-8") as f: print(f.read()) # 2,一个with 语句可以操作多个文件,产生多个文件句柄。 with open("trial", encoding = "utf-8") as f1, open("文件的写", encoding = "utf-8", mode = "w") as f2: print(f1.read()) f2.write("你好毒哟")
这里要注意一个问题,虽然使用with语句方式打开文件,不用你手动关闭文件句柄,比较省事儿,但是依靠其自动关闭文件句柄,是有一段时间的,这个时间不固定,所以这里就会产生问题,如果你在with语句中通过r模式打开t1文件,那么你在下面又以a模式打开t1文件,此时有可能你第二次打开t1文件时,第一次的文件句柄还没有关闭掉,可能就会出现错误,他的解决方式只能在你第二次打开此文件前,手动关闭上一个文件句柄。
文件的修改
步骤:
1. 以读的模式打开源文件
2. 以写的模式创建一个新文件
3. 将源文件读出来的需要修改的内容进行修改以后写入新文件
4. 将源文件删除
5. 将新文件重命名为源文件
文件的数据是存放于硬盘上的,因而只存在覆盖、不存在修改这么一说,我们平时看到的修改文件,都是模拟出来的效果,具体的说有两种实现方式:
方式一:将硬盘存放的该文件的内容全部加载到内存,在内存中是可以修改的,修改完毕后,再由内存覆盖到硬盘(word,vim,nodpad++等编辑器)
import os # 调用系统模块
with open("自述", encoding = "utf-8") as read_f, open("自述修改", encoding = "utf-8", mode = "w") as write_f: contents = read_f.read() # 全部读入内存,如果文件很大,会很卡 contents = contents.replace("alex", "DSB") # 在内存中完成修改 write_f.write(contents) # 一次性写入新文件os.remove("自述") # 删除原文件os.rename("自述修改", "自述") # 将新建的文件重命名为原文件
方式二:将硬盘存放的该文件的内容一行一行地读入内存,修改完毕就写入新文件,最后用新文件覆盖源文件
with open("自述", encoding = "utf-8") as read_f, open("自述修改", encoding = "utf-8", mode = "w") as write_f: for line in read_f: line = line.replace("DSB", "alex") write_f.write(line) os.remove("自述") os.rename("自述修改", "自述")
# 有关清空的问题 # 关闭文件句柄,再次以w 模式打开此文件时,才会清空 with open("文件的写", mode = "w", encoding = "utf-8") as f: f.write("好嗨哦") f.write("好嗨哦") f.write("好嗨哦")