文件操作
什么是文件
文件是操作系统提供给用户/应用程序操作硬盘的一种虚拟的概念/接口。
用户/应用程序想要读写硬盘上保存的数据时,调用文件接口的过程:
- 向操作系统发送相关请求;
- 操作系统执行请求修改硬盘数据的请求
总结:用户\应用程序 -----> 操作系统 -----> 硬盘
用代码操作文件的基本流程
open方法
缺点,需要手动的去关闭文件
# 1. 打开文件,由应用程序向操作系统发起系统调用open(...)
# 操作系统打开该文件,对应一块硬盘空间,并返回一个文件对象赋值给一个变量file
file = open("02.txt", mode="rt", encoding="utf-8")
# 2. 调用文件对象下的读/写方法,会被操作系统转换为读/写硬盘的操作
content = file.read()
print(content)
# # 3. 向操作系统发起关闭文件的请求,回收系统资源
file.close()
# 文件中的内容
jack-521
eva-113
amigo-445
with open
文件操作完成后一定要及时回收操作系统资源和程序资源。但是这个
file.close()
和del file
很容易在编写代码的过程中被忘记掉。上下文管理器,1、在执行完子代码块后,with 会自动执行
file.close()
通过文件句柄file操作读写操作,所有的读写操作写在with下面的自带吗块中。程序退出字代码块的时候会自动回收系统资源。
with open("02.txt", mode="rt", encoding="utf-8") as file:
content = file.read()
print(content)
# 文件中的内容
jack-521
eva-113
amigo-445
同时打开多个文件
with open("02.txt", mode="rt", encoding="utf-8") as f1, open("db.txt", mode="wt", encoding="utf-8") as f2:
content = f1.read()
f2.write(content)
如果太长,可以用\换行,下面功能和上面一样
with open("02.txt", mode="rt", encoding="utf-8") as f1, \
open("db.txt", mode="wt", encoding="utf-8") as f2:
content = f1.read()
f2.write(content)
mode参数详解
t模式(默认)
控制文件读写内容的模式:t模式、b模式; **指的是读写的内容是字符串还是Bytes
t模式(默认的模式),一般如果是操作文本,t可以简写,当读取文件的时候,也可以直接写成
with open("db.txt", encoding=utf-8) as file
,省略掉文件模式。
wt = w
rt = r(或者不写)
at = a
注意点:
- 读写都是以
str
(Unicode)为单位的- 文本文件,必须指定
encoding="utf8"
b模式(二进制/bytes)
如果文件的
mode
为b模式,那么不需要指定encoding
参数,不然会报错,常见的后缀:图片、音乐、视频、压缩文件等,都是需要使用b模式去读写的,所有文件都可以使用二进制模式去操作。
常见的文件模式
'r'
:以只读模式打开文件。文件的指针将会放在文件的开头,如果文件不存在则会引发FileNotFoundError
错误。'w':以写入模式打开文件。如果文件存在,则会清空文件内容;如果文件不存在,则会创建一个新文件。文件的指针将会放在文件的开头。
'x':以独占写入模式打开文件。如果文件存在,则会引发
FileExistsError
错误;如果文件不存在,则会创建一个新文件。文件的指针将会放在文件的开头。'a':以追加模式打开文件。如果文件存在,则文件指针将会放在文件的末尾;如果文件不存在,则会创建一个新文件。
'b':以二进制模式打开文件。这个模式可以与上述模式组合使用,如'
rb
'、'wb
'等。它用于处理二进制文件,如图片、视频等。't':以文本模式打开文件(默认模式)。这个模式可以与上述模式组合使用,如'rt'、'wt'等。它用于处理文本文件,如
TXT
文件等。'+':以读写模式打开文件,可以与上述模式组合使用,如'r+'、'w+'等。它允许对文件进行读写操作。
总结:
r
只读模式
w
只写模式
a
只追加写模式
+
:r+
、w+
、a+
(了解即可)一般情况下用到的
r w a
模式比较多,b
模式不需要指定encoding
,t和b不能单独使用,必须跟r/w/a模式连用。通过什么编码写入的文件,那么读取文件就需要采用一样的编码才可以。
读写操作模式 | 说明 | 备注 |
---|---|---|
r | 只读模式,默认 | 文件没有关闭时,第二次读将从指针上次停留的位置开始接着往下读 |
w | 只写模式 | mode="w" file=read()会报错 |
a | 追加模式 | a模式内不可读文件、指针再最后 |
+ | 读写模式,了解 | 在平时工作中,我们只单纯使用r/w/a,要么只读,要么只写,一般不用可读可写的模式 |
x | 只写模式(不可读,了解) | 文件不存在新建;文件存在则报错 |
b | 二进制 | 不需要指定encoding |
r模式演示
with open("02.txt", mode="rt", encoding="utf-8") as file:
content = file.read()
print(content)
w模式演示
with open("02.txt", mode="wt", encoding="utf-8") as file:
content = file.read()
print(content)
a模式演示
with open("02.txt", mode="at", encoding="utf-8") as file:
content = file.read()
print(content)
b模式演示
import requests
url = "https://pic.netbian.com/uploads/allimg/231111/010350-16996358307f29.jpg"
response = requests.get(url)
content = response.content
with open("BeautifulGirl.jpg", "wb") as file:
file.write(content)
print("写入完成!")
自制简易的文件拷贝工具
old_path = r"D:\Python\girl.jpg"
new_path = r"D:\Python\img\girl.jpg"
with open(r"{}".format(old_path), "rb") as f1, \
open(r"{}".format(new_path), "wb") as f2:
data = f1.read()
f2.write(data)
编码方式模式
编码方式模式指的是
open()
中的encoding
参数的使用。encoding参数是用在文本文件中,且仅使用在t模式下。
当读写操作模式是r时,encoding表示解码的方式,即将其他二进制数据解码为Unicode格式二进制数据读到内存;
当读写操作模式是w时,encoding表示编码的方式,即将Unicode格式二进制数据编码为其他二进制数据保存到硬盘。
操作文件的方法
读操作
read()
读取所有内容,执行完该操作后,文件指针会移动到文件末尾。
喜欢的句子.txt
你懂的越多,你就越像这个世界的孤儿。
with open("喜欢的句子.txt", encoding="utf-8") as file:
data = file.read()
print(data) # 你懂的越多,你就越像这个世界的孤儿。
注意:read(n)在t模式是n指字符数,b模式下n指字节数
with open("喜欢的句子.txt", encoding="utf-8") as file:
data = file.read(5) # 读取五个字符
print(data) # 你懂的越多
读取一张图片
with open("BeautifulGirl.jpg", "rb") as file:
content = file.read()
print(content)
x90C/\x07\xb6\x1dO\xeb\xe9\xe9\xc5{\x8c\xdf\xb2/\xc4\xe89\xb4\xf8\xa1\xa1\xdc \x18\xdby\xe1i\x83\x93\xc6s%\xbe\xa9\n\x9c\x0e\xfb\x17\x04\x8f\xc2\x9c\xdf\xb2\xff\x00\xc6(X\x08<U\xe0\xfb\xb5\x1fx\xcbg\xaaY\xb6\xe0{*=\xe0\xc7\x7f\xbc\xa7\'\x1c\xf4\xa5\xec\xf7\xbbZ\xf4\xbbk\xa5\xae\x9e\x9d\xf6\xed~\xa6\xb1\xc5\xd2N\xf7OO=\xd5\xba;$\xdd\xee\xb6\xd9\xf5\xb1\xf3\xbe\xad\xf0\x9f\xe1\x86\xb8%]W\xc0\x1e\x0e\xbd\xf3\x83nk\x8f\x0f\xe92H\xe4\xf5,\xc6\xdfq-\x93\x93\x9f\xd35\xe3:\xdf\xec\x83\xfb;......
with open("BeautifulGirl.jpg", "rb") as file:
while True:
data = file.read(1024)
if len(data) == 0:
break
print(data)
x90C/\x07\xb6\x1dO\xeb\xe9\xe9\xc5{\x8c\xdf\xb2/\xc4\xe89\xb4\xf8\xa1\xa1\xdc \x18\xdby\xe1i\x83\x93\xc6s%\xbe\xa9\n\x9c\x0e\xfb\x17\x04\x8f\xc2\x9c\xdf\xb2\xff\x00\xc6(X\x08<U\xe0\xfb\xb5\x1fx\xcbg\xaaY\xb6\xe0{*=\xe0\xc7\x7f\xbc\xa7\'\x1c\xf4\xa5\xec\xf7\xbbZ\xf4\xbbk\xa5\xae\x9e\x9d\xf6\xed~\xa6\xb1\xc5\xd2N\xf7OO=\xd5\xba;$\xdd\xee\xb6\xd9\xf5\xb1\xf3\xbe\xad\xf0\x9f\xe1\x86\xb8%]W\xc0\x1e\x0e\xbd\xf3\x83nk\x8f\x0f\xe92H\xe4\xf5,\xc6\xdfq-\x93\x93\x9f\xd35\xe3:\xdf\xec\x83\xfb;......
readline
读取一行内容,光标移动到第二行首部
喜欢的句子.txt
你懂的越多,你就越像这个世界的孤儿。
山腰的风景很美
然而
我还是
想去山顶看看
with open("喜欢的句子.txt", encoding="utf-8") as file:
data = file.readline()
print(data)
data = file.readline()
print(data)
data = file.readline()
print(data)
data = file.readline()
print(data)
data = file.readline()
print(data)
你懂的越多,你就越像这个世界的孤儿。
山腰的风景很美
然而
我还是
想去山顶看看
with open("喜欢的句子.txt", encoding="utf-8") as file:
while True:
data = file.readline()
if len(data) == 0:
break
print(data)
你懂的越多,你就越像这个世界的孤儿。
山腰的风景很美
然而
我还是
想去山顶看看
readlines
读取每一行内容,存放于列表中
列表中的每一项后面都会包括一个
\n
的换行符
喜欢的句子.txt
你懂的越多,你就越像这个世界的孤儿。
山腰的风景很美
然而
我还是
想去山顶看看
with open("喜欢的句子.txt", encoding="utf-8") as file:
data = file.readlines()
print(data)
['你懂的越多,你就越像这个世界的孤儿。\n', '山腰的风景很美\n', '然而\n', '我还是\n', '想去山顶看看']
读操作注意事项
注意1:三个读函数都可以用在t模式和b模式下,t模式读出来的是字符,b模式下读出来的是Bytes字节(二进制)
注意2:
read(n)
在t模式是n指字符数,b模式下n指字节数
写操作
write
记得加上换行符
with open("喜欢的句子.txt", "wt", encoding="utf-8") as file:
sentence = "你懂的越多,你就越像这个世界的孤儿。\n跟着光,成为光,散发光。\n"
file.write(sentence)
你懂的越多,你就越像这个世界的孤儿。
跟着光,成为光,散发光。
通过b模式去写入,不需要指定encoding
with open("喜欢的句子.txt", "wb") as file:
sentence = "你懂的越多,你就越像这个世界的孤儿。\n跟着光,成为光,散发光。\n"
file.write(sentence.encode("utf-8"))
你懂的越多,你就越像这个世界的孤儿。
跟着光,成为光,散发光。
writelines
记得列表里面的每一项后面加上一个换行符,不然内容会写到一起
dataList = ['你懂的越多,你就越像这个世界的孤儿。\n', '跟着光,成为光,散发光。\n']
with open("喜欢的句子.txt", "wt", encoding="utf-8") as file:
file.writelines(dataList)
你懂的越多,你就越像这个世界的孤儿。
跟着光,成为光,散发光。
with open("喜欢的句子.txt", "wb") as file:
file.writelines(["跟着光\n".encode("utf-8"), "成为光\n".encode("utf-8"), "散发光\n".encode("utf-8")])
跟着光
成为光
散发光
如果是纯英文字符,可以直接加前缀b得到bytes类型
sentence = b"talk is cheap, show me the code.\n"
with open("喜欢的句子.txt", "wb") as file:
file.writelines([sentence])
talk is cheap, show me the code.
写操作注意事项
- 如果是纯英文字符,可以直接加前缀b得到bytes类型
'上'.encode('utf-8')
等同于bytes('上',encoding='utf-8')
- 强调:
read()
与readlines()
都是将内容一次性读入内容,如果内容过大会导致内存溢出,若还想将内容全读入内存,则必须分多次读入.
了解的方法
f.readable() # 文件是否可读 r模式为True w或者a模式为Fale
f.writable() # 文件是否可读 r模式为False
f.closed # 文件是否关闭
f.encoding # 如果文件打开模式为b,则没有该属性
f.flush() # 立刻将文件内容从内存刷到硬盘
f.name
f.tell() # 获取文件指针当前位置
bytes方法
sentence = "talk is cheap, show me the code."
data = sentence.encode("utf-8")
print(data) # b'talk is cheap, show me the code.'
sentence = "talk is cheap, show me the code."
data = bytes(sentence, "utf-8")
print(data) # b'talk is cheap, show me the code.'
避免读文件时内存溢出的方式
方式1
with open("喜欢的句子.txt", encoding="utf-8") as file:
for line in file:
print(line) # 同一时刻只读入一行内容到内存中
方式2
with open("喜欢的句子.txt", encoding="utf-8") as file:
while True:
data = file.read(1024) # 同一时刻只读入1024个Bytes到内存中
if len(data) == 0:
break
print(data)
控制文件指针移动seek
# 之前文件内指针的移动都是由读/写操作而被动触发的,若想读取文件某一特定位置的数据,则需要用f.seek方法主动控制文件内指针的移动,详细用法如下:
# f.seek(指针移动的字节数,模式控制):
# 模式控制:
# 0: 默认的模式,该模式代表指针移动的字节数是以文件开头为参照的(参照物永远是文件开头位置)
# 1: 该模式代表指针移动的字节数是以当前所在的位置为参照的(参照物是指针当前所在位置)
# 2: 该模式代表指针移动的字节数是以文件末尾的位置为参照的(参照物是文件末尾的位置,应该倒着数)
# 补充:当指针移动的字节数n为整数时,表示往后移动;当n为负数时,表示往前移动;
# 强调:其中0模式可以在t或者b模式使用,而1跟2模式只能在b模式下用,012三种模式b模式下都可以用.
# 注意:由于在t模式下,会将读取的内容自动解码,所以必须保证读取的内容是一个完整中文数据,否则解码失败报错
content.txt
hero小满
with open("content.txt", encoding="utf-8") as file:
file.seek(4, 0)
print(file.read()) # 小满
with open("content.txt", "rb") as file:
file.seek(4, 0) # 4个指针
file.seek(3, 1) # 一个中文字占位三个字节
print(file.read().decode("utf-8")) # 满
with open("content.txt", "rb") as file:
file.seek(-6, 2) # 当seek为2的时候,第一个参数需要为负数
print(file.read().decode("utf-8")) # 小满
文件修改实战
1、硬盘空间是无法修改的,硬盘中数据的更新都是用新内容覆盖旧内容
2、内存中的数据是可以修改的
文件对应硬盘空间,硬盘不能修改也就是说文件不能修改。
想要修改文件的思路是将硬盘上的文件内容读入内存,在内存中修改完毕后再覆盖到硬盘上。
方案1实现思路:将文件内容发一次性全部读入内存,然后在内存中修改完毕后再覆盖写回原文件
优点: 在文件修改过程中同一份数据只有一份
缺点: 会过多地占用内存
content.txt
全体渣男起立,入队宣誓。
我宣示:做个俗人,不谈亏欠,不负遇见。做个俗人,没心没肺。没感情。
安稳自由,谈笑风生。做个俗人,只沾酒沾烟,不染感情。
做个俗人,忘南不归。做个俗人,贪财好色,一身正气。
做个俗人,你我无心,永不用心。从此寻花问柳,闭口不谈一生厮守。从此红灯绿酒,再也不掐牵谁。
with open("content.txt", encoding="utf-8") as file:
data = file.read()
with open("content.txt", "wt", encoding="utf-8") as file:
file.write(data.replace("渣男", "海王"))
全体海王起立,入队宣誓。
我宣示:做个俗人,不谈亏欠,不负遇见。做个俗人,没心没肺。没感情。
安稳自由,谈笑风生。做个俗人,只沾酒沾烟,不染感情。
做个俗人,忘南不归。做个俗人,贪财好色,一身正气。
做个俗人,你我无心,永不用心。从此寻花问柳,闭口不谈一生厮守。从此红灯绿酒,再也不掐牵谁。
方案2实现思路:以读的方式打开原文件,以写的方式打开一个临时文件,一行行读取原文件内容,修改完后写入临时文件...,删掉原文件,将临时文件重命名原文件名。
优点: 不会占用过多的内存。
缺点: 在文件修改过程中同一份数据存了两份
import os
with open("content.txt", encoding="utf-8") as f1, \
open("content.txt.swap", "wt", encoding="utf-8") as f2:
for line in f1:
f2.write(line.replace("渣男", "海王"))
os.remove("content.txt")
os.rename("content.txt.swap", "content.txt")
全体海王起立,入队宣誓。
我宣示:做个俗人,不谈亏欠,不负遇见。做个俗人,没心没肺。没感情。
安稳自由,谈笑风生。做个俗人,只沾酒沾烟,不染感情。
做个俗人,忘南不归。做个俗人,贪财好色,一身正气。
做个俗人,你我无心,永不用心。从此寻花问柳,闭口不谈一生厮守。从此红灯绿酒,再也不掐牵谁。
原始文件内容如下:
张一蛋 山东 179 49 12344234523
李二蛋 河北 163 57 13913453521
王全蛋 山西 153 62 18651433422题目要求:
通过文件操作变成下面的结果
张一蛋(妇女主任) 山东 179 49 12344234523
张二蛋(村长) 河北 163 57 13913453521
王全蛋(书记) 山西 153 62 18651433422
data.txt
就是原始文件内容,result.txt
就是最终结果
dic = {
"张一蛋": "张一蛋(妇女主任)",
"李二蛋": "张二蛋(村长)",
"王全蛋": "王全蛋(书记)"
}
with open("data.txt", "r+", encoding="utf-8") as f1, open("result.txt", "w", encoding="utf-8") as f2:
for line in f1.read().splitlines():
name = line.split()[0] # 转成列表取出姓名
new_text = line.replace(name, dic.get(name))
f2.write(new_text + "\n")
本文作者:小满三岁啦
本文链接:https://www.cnblogs.com/ccsvip/p/17877604.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。