文件操作的点点滴滴
一 文件操作
使用 python 来读写 文件 是件 简单的操作,我们使用python的 open()函数 来打开一个文件,获取到
文件句柄,然后通过文件句柄 就可以 进行各种操作了,根据打开方式的不同,能够执行的操作也有相应的
差异
打开文件的 方式,r w a r+ w+ a+ rb wb ab r+b w+b a+b
二 只读模式 (r, rb)
r 表示 只读 f = open("tl.txt",mode = "r",encoding = "utf-8") content = f.read() print(content) f.close() # # 需要注意的是 encoding 表示 编码集,根据文件 的实际保存编码进行获取数据, # # 对于我们而言,更多的是 utf-8 , 有些 gbk
rb 读取出来的 数据是 bytes 类型,在 rb 模式下,不能 选择 encoding 字符街 一般操作 非文本 文件,也可以操作文本文件, 视频 ,音频 等 f = open("tl.txt",mode = "rb") content = f.read() print(content) f.close() # # rb的作⽤: 在读取非文本文件的时候. 比如读取MP3. 图像. 视频等信息的时候就需要用到rb # 因为这种数据是没办法直接显示出来的. 在我们上件上传下载的时候还会用到. # 还有.我们看到的 直播,实际上都是 这种数据
绝对路径 和 相对路径
1.绝对路径: 从磁盘根目录开始 一直到 文件名
2.相对路径: 同一个文件夹下的文件,相对于当前这个程序 所在的 文件夹而言,如果在同一个文件夹中
则相对路径就是这个文件名,如果在上一层文件夹,则要用 ../,出一层 ../ 一层
## 推荐使用 相对路径: 因为在我们把程序拷贝给别人使用的是,直接把项目拷贝走就能运行,但如果是
## 使用的绝对路径,那还需要拷贝外部的文件
读取的方法:
1.read() 将文件中的全部内容读取出来, 弊端:占内存,如果文件过大,容易导致内存奔溃
f = open("alex.txt",mode = "r",encoding = "utf-8") content = f.read() print(content)
f.close() ## 注意 : 读取完的 文件句柄 一定要关闭
# 结果:曾经有一段真挚的爱情摆在我的面前,我没有好好珍惜, 直到失去后才懂得, 人生最大的痛苦莫过于此,如果........ 可惜,没有如果.....
2.read(n) 读取 n 个 字符 (中文里字符就是汉字) , 需要注意的是,如果再次读取,那么会在当前位置继续去读
而不是从头读,如果使用的是 rb 模式,则读取出来的是 n 个字节
f = open("tl.txt",mode = "r",encoding = "utf-8") content = f.read(3) print(content) # 结果是: # 曾经有 f = open("tl.txt",mode = "rb") content = f.read() print(content) # 结果是: # b'\xe5\x8f\x f = open("tl.txt",mode = "r",encoding = "utf-8") content1 = f.read(3) content2 = f.read(3) print(content1) print(content2)
f.close() ## 注意 : 读取完的 文件句柄 一定要关闭
# 结果是: # 曾经有 # 一份真
3.readline() 一次读取一行 数据,注意:readline() 结尾,注意每次读取出来的数据都会有一个\n,
需要我们使用 strip() 方法 来去掉 \n 或者空格
f = open("t1.txt",mode = "r",encoding = "utf-8") content1 = f.readline() content2 = f.readline() content3 = f.readline() content4 = f.readline() content5 = f.readline() content6 = f.readline() content7 = f.readline()
f.close() ## 注意 : 读取完的 文件句柄 一定要关闭
# 结果是:
# 曾经有一段真挚的爱情摆在我的面前,
# 我没有好好珍惜,
# 直到失去后才懂得,
# 人生最大的痛苦莫过于此,
4.readlines() 将 每一行形成一个元素,放到 一个列表中,将所有的内容读取出来,所以也是容易出现
内存奔溃的问题,不推荐使用
f = open("t1.txt",mode = "r",encoding = "utf-8") lst = f.readlines() for line in lst: print(line.strip())
f.close() ## 注意 : 读取完的 文件句柄 一定要关闭
5.循环读取,这种方式是最好的,每次读取一行内容,不会产生内存溢出的问题
f = open("t1.txt",mode = "r",encoding = "utf-8") for line in f: print(line.strip()) f.close() ## 注意 : 读取完的 文件句柄 一定要关闭
三 写模式 (w, wb)
写的时候 注意,如果没有文件,则会创建文件,如果文件存在,则将原文件中的 内容全部删除,再 写入
##### 慎用 慎用 慎用
f = open("t1.txt",mode = "w",encoding = "utf-8") f.write("王祖贤") f.read() # not readable 模式是 w , 不可以执行读操作 f.flush() # 刷新 f.close()
wb 模式下,可以不指定 打开文件的编码,但是在写文件的时候必须 将字符串 转化成 utf-8 的bytes 数据
f = open("t1.txt",mode="wb") f.write("李若彤",encoding = "utf-8") f.flush() f,close()
四 追加 ( a ,ab)
在追加模式下,我们写入的内容会追加在文件的 结尾
f = open("t1.txt",mode = "a",encoding = "utf-8") f.write("香港武打明星都有谁??") f.flush() f.close()
五 读写模式(r+,r+b)
对于读写模式,必须先是读,因为默认 光标是在开头的 , 准备读取的,,当读完了之后再进行写入
我们使用频率最高的模式就是 r+
f = open("t1.txt",mode = "r+",encoding = "utf-8") content = f.read() f.write("最喜爱的香港女明星:") print(content) f.flush() f.close() ## 结果 ,正常读取之后,写在结尾
## 如果写在先,写的内容会将开头的内容改成 你写的内容, 再读取的话,是在写之后读取,这样文件就被你
## 操作坏了,慎用啊 ,谨记啊 !!!!!!!!!!!
六 写读(w+ , w+b)
w 家族的标志性操作,只有用 w 写,一上来先清空文件,再 写,最后再读取,不常用
f = open("t1.txt",mode = "w+",encoding = "utf-8") f.write("哈哈,清空了") # f.seek(0) # 将 光标移动到开头,就可以读到 "哈哈,清空了" content = f.read() print(content) f.flush() f.close() ### 结果 ,什么都读不到的 ,想要读到内容,移动光标
# # 有朋友 认为 先读就行了. 哈哈哈,错了,因为,w 家族模式下,一开始是读不到内容的,所以很少用
七 追加写 读 (a+)
a+ 模式下,不论先读还是 后读 都是 读不到内容的
八 其他相关操作
1.seek( n) 移动 光标 n 个位置, 注意,移动的单位是 bytes,所以 如果是 utf-8 的 中文要是3 的倍数
想想,为什么呢?? 因为 utf-8 中,一个中文 占 3 个字节啊
通常我们使用 seek 都是移动到 开头 或者 结尾
seek(0) 移到开头
seek(0,2) 移动到结尾
seek 的第二个 参数 表示 从 哪个位置 进行 便宜,默认是 0 ,表示开头
1,表示当前位置
2,表示结尾
f = open("t1.txt",mode = "r+",encoding = "utf-8") f.seek(0) # 光标移动到开头 content = f.read() # 读取内容 , 此时 光标 移动到 结尾 print(content) f.seek(0) # 再次移动到 开头 f.seek(0,2) # 将光标移动到 结尾 content1 = f.read() # 读取内容, 什么都没有 print(content1) f.seek(0) # 移动到开头 f.write("张敏") # 写入 信息,此时 光标在 6 , 中文 2 * 3 = 6 f.flush() f.close()
2.tell() 使用 tell() 可以 帮我们 获取到 当前 光标的 位置
f = open("t1.txt",mode = "r+",encoding = "utf-8") f.seek(0) # 光标移动到开头 content = f.read() # 读取内容 , 此时 光标 移动到 结尾 print(content) f.seek(0) # 再次移动到 开头 f.seek(0,2) # 将光标移动到 结尾 content1 = f.read() # 读取内容, 什么都没有 print(content1) f.seek(0) # 移动到开头 f.write("张敏") # 写入 信息,此时 光标在 6 , 中文 2 * 3 = 6 print(f.tell()) # 光标位置 6 f.flush() f.close()
3.truncate() 截断文件
f = open("t1.txt",mode = "w",encoding = "utf-8") f.write("西西") # 写入 2 个字符 f.seek(3) # 移动光标到3,也就是两个字中间 f.truncate() # 删除光标 后面的所有的 内容 f.close() f = open("t1.txt",mode = "r+",encoding = "utf-8") content = f.read(2) # 读取 2个 字符 f.seek(3) print(f.tell()) f.truncate() # 后面的所有的内容都删掉了 f.flush() f.close()
#### 注意,注意,注意: 在 r+ 模式下 ,如果读取了内容,不论读取的内容多少, 光标显示的多少,再 写入
或者操作文件的时候 都是在结尾 进行的 操作
所以,如果想 作 截断操作,记得,请一定记得!!! 先挪动 光标,挪动到你想 截断的位置,然后再 进行截断
关于 truncate(n) ,如果 给出了 n ,则从开头数到 n 截断,如果没有 n ,则从当前位置截断,后面的内容都
会被 删除
九 修改 文件 以及 另一种 打开文件的方式
文件修改:只能将 文件 中的 内容 读取到 内存中,将信息修改完毕,然后将原文件 删除,将新文件的
名字改成 老文件的名字,就完成了
## 文件修改 用到的 模块 import os with open("ti.txt",mode = "r",encoding = "utf-8")as f,\ open("t1_fuebn,txt",mode = "w",encoding = "utf-8")as f1: content = f.read() fuben_content = content.replace("王祖贤","张敏") f1.write(fuben_content) os.remove("t1.txt") # 删除 源文件 os.rename("t1_fuben.txt","t1.txt") # 重命名 新文件 ######## 弊端::; 一次读取内容,和我们前面说过的 一样,内存容易溢出 ########### 解决方案:: 一行一行读 import os with open("ti.txt",mode = "r",encoding = "utf-8")as f,\ open("t1_fuebn,txt",mode = "w",encoding = "utf-8")as f1: for line in f: fuben_line = line.replace("哈哈哥","西西姐") f1.write(fuben_line) os.remove("t1.txt") os.rename("t1_fuben.txt","t1.txt")