文件操作
创新互联公司一直通过网站建设和网站营销帮助企业获得更多客户资源。 以"深度挖掘,量身打造,注重实效"的一站式服务,以成都网站设计、网站制作、移动互联产品、成都营销网站建设服务为核心业务。十余年网站制作的经验,使用新网站建设技术,全新开发出的标准网站,不但价格便宜而且实用、灵活,特别适合中小公司网站制作。网站管理系统简单易用,维护方便,您可以完全操作网站资料,是中小公司快速网站建设的选择。初识文件操作
使用python来读写文件是非常简单的操作,我们使用open()函数来打开某个文件,获取到文件句柄,然后通过文件句柄就可以进行各种各样的操作了。根据打开形式的不同能够执行的操作也会有相应的差异。操作文件的方式一般有如下:
r, w, a, r+, w+, a+, rb, wb, ab, r+b, w+b, a+b
默认使用的是r(只读)模式
只读操作(r, rb)
f = open("python", mode="r", encoding="utf-8")
content = f.read()
print(content)
f.close()
python.txt
这是python文件
运行结果:
这是python文件
Process finished with exit code 0
需要注意encoding表示编码集,根据文件的实际保存编码进行获取数据,对于我们来说,使用更多的是utf-8。
rb. 读取出来的数据是bytes类型,,在rb模式下,不能选择encoding字符集。
f = open("python", mode="rb")
content = f.read()
print(content)
f.close()
python.txt
这是python文件
运行结果:
b'\xe8\xbf\x99\xe6\x98\xafpython\xe6\x96\x87\xe4\xbb\xb6'
Process finished with exit code 0
rb的作用: 在读取非文本文件的时候. 比如读取MP3、图像、视频等信息的时候就需要用到rb。因为这种数据是没办法直接显示出来的. 在后面文件上传下载的时候还会用到。还有,我们看的直播,实际上都是这种数据。
路径
一般分为绝对路径和相对路径:
1. 绝对路径:从磁盘根目录开始一直到文件名。
2. 相对路径:同一个文件夹下的文件,相对于当前这个程序所在的文件夹而言,如果在同一个文件夹中。则相对路径就是这个文件名,如果在上一层文件夹,则要使用../表示上一层文件,如果在上多层文件夹中,则需要使用多次../。
一般在开发过程中推荐大家使用相对路径。因为在我们把程序拷贝给别人使用的时候. 直接把整个项目文件拷贝出去就能运行,但是如果使用绝对路径,那还需要拷贝外部的文件。
获取文件
read()
将文件中的内容全部读取出来。弊端:占内存。如果文件过大,容易导致内存崩溃,使用时应该小心谨慎。
f = open("../FileOne/静夜思.txt", mode="r", encoding="utf-8")
content = f.read()
print(content)
静夜思.txt
床前明月光
疑是地上霜
举头望明月
低头思故乡
运行结果:
床前明月光
疑是地上霜
举头望明月
低头思故乡
Process finished with exit code 0
read(n)
读取n个字符,需要注意的是,如果再次读取,那么会在当前位置继续去读而不是从头读,如果使用的是rb模式,则读取出来的是n个字节。
f = open("../FileOne/静夜思.txt", mode="r", encoding="utf-8")
content = f.read(4)
contentOne = f.read(5)
print(content)
print(contentOne)
静夜思.txt
床前明月光
疑是地上霜
举头望明月
低头思故乡
运行结果:
床前明月
光
疑是地
Process finished with exit code 0
值得注意的是,在这里换行符表示一个字节。前面4个字节,后面接着输出5个字节。
f = open("../FileOne/静夜思.txt", mode="rb")
content = f.read(4)
contentOne = f.read(5)
print(content)
print(contentOne)
静夜思.txt
床前明月光
疑是地上霜
举头望明月
低头思故乡
运行结果:
b'\xe5\xba\x8a\xe5'
b'\x89\x8d\xe6\x98\x8e'
Process finished with exit code 0
readline()
一次读取一行数据,注意:readline()结尾,注意每次读取出来的数据都会有一个\n 。所以呢,需要我们使用strip()方法来去掉\n或者空格,当然,我们也可以在print后面加上end=""去掉空格。
f = open("../FileOne/静夜思.txt", mode="r", encoding="utf-8")
contentOne = f.readline()
contentTwo = f.readline()
contentThree = f.readline()
contentFour = f.readline()
print(contentOne.strip())
print(contentTwo.strip())
print(contentThree, end="")
print(contentFour, end="")
静夜思.txt
床前明月光
疑是地上霜
举头望明月
低头思故乡
运行结果:
床前明月光
疑是地上霜
举头望明月
低头思故乡
Process finished with exit code 0
readlines()
将每一行形成一个元素,放到一个列表中,将所有的内容都读取出来,所以也是,容易出现内存崩溃的问题,一般不推荐不推荐使用。
f = open("../FileOne/静夜思.txt", mode="r", encoding="utf-8")
lst = f.readlines()
print(lst)
for line in lst:
print(line.strip())
静夜思.txt
床前明月光
疑是地上霜
举头望明月
低头思故乡
['床前明月光\n', '疑是地上霜\n', '举头望明月\n', '低头思故乡']
床前明月光
疑是地上霜
举头望明月
低头思故乡
Process finished with exit code 0
从列表里面我们可以看出,每次获取的行后面都会有换行符/n。因此,打印过程中我们应该使用strip()或者end = ()去掉换行。
循环读取
f = open("../FileOne/静夜思.txt", mode="r", encoding="utf-8")
for line in f:
print(line.strip())
静夜思.txt
床前明月光
疑是地上霜
举头望明月
低头思故乡
运行结果:
床前明月光
疑是地上霜
举头望明月
低头思故乡
Process finished with exit code 0
这种方式是事先就组好了,每次读取一行的内容,不会产生内存溢出的问题。
注意:
在每次读取完文件时,应该关闭文件句柄。f.closed()
在执行操作过后可使用刷新机制对文件进行刷新。f.flush()
写模式(r,rw)
写的时候注意,如果没有文件,则会创建文件,如果文件存在,则将原件中原来的内容删除,再写入新内容。
f = open("⼩娃娃", mode="w", encoding="utf-8")
f.write("⾦⽑狮王")
# f.read() # 尝试读取文件,此时只是写,抛出io.UnsupportedOperation: not readable
f.flush() # 刷新. 养成好习惯
f.close()
创建了文件:小娃娃
⾦⽑狮王
运行结果:
Process finished with exit code 0
本次文件写操作执行完毕后,程序结束,控制台没有输出值,只是在列表中创建了文件。
f = open("⼩娃娃", mode="wb")
f.write("⾦⽑狮王".encode("utf-8"))
f.flush()
f.close()
创建文件:小娃娃
⾦⽑狮王
运行结果:
Process finished with exit code 0
wb模式下,可以不指定文件的编码,但是在写文件的时候必须将字符串转换为utf-8的bytes数据,如果不转化,将会出现一下的错误。
TypeError: a bytes-like object is required, not 'str'
追加(a,ab)
在追加模式下. 我们写入的内容会追加在文件的结尾.
f = open("⼩娃娃", mode="a", encoding="utf-8")
f.write("麻花藤的最爱")
f.write("是小学生")
f.flush()
f.close()
创建文件:小娃娃
麻花藤的最爱是小学生
运行结果:
Process finished with exit code 0
f = open("⼩娃娃", mode="ab")
f.write("麻花藤的最爱".encode())
f.write("是小学生".encode())
f.flush()
f.close()
创建文件:小娃娃
麻花藤的最爱是小学生
运行结果:
Process finished with exit code 0
由于编译器默认的是utf-8,所以在小娃娃文件中显示的是未改变的字符。
读写模式(r+,r+b)
对于读写模式,必须是先读。因为默认光标是在开头的,准备读取的,当读完了之后再进行写入,我们以后使用频率高的模式就是r+。
f = open("⼩娃娃", mode="r+", encoding="utf-8")
content = f.read()
f.write("麻花藤的最爱")
print(content)
f.flush()
f.close()
运行前的文件:小娃娃
麻花藤的最爱
运行后的文件:小娃娃
麻花藤的最爱麻花藤的最爱
运行结果:
麻花藤的最爱
Process finished with exit code 0
在正常的读取后,文件的写入在结尾。
下面演示错误操作:
f = open("⼩娃娃", mode="r+", encoding="utf-8")
f.write("哈哈")
content = f.read()
print(content)
f.flush()
f.close()
运行前的文件:小娃娃
麻花藤的最爱
运行后的文件:小娃娃
哈哈藤的最爱
运行结果:
藤的最爱
Process finished with exit code 0
在没有任何操作之前,默认的光标在开头,当写入“哈哈”以后,“麻花”二字被覆盖,且光标往后移动了两个位置,默认读取从光标后开始读取。
总结,在r+模式下,必须是先读取,再写入。
写读(w+,w+b)
先将所有的内容清空,然后写入,最后读取,但是读取的内容是空的,一般不常用。
f = open("⼩娃娃", mode="w+", encoding="utf-8")
f.write("哈哈")
content = f.read()
print(content)
f.flush()
f.close()
运行前的文件:小娃娃
麻花藤的最爱
运行后的文件:小娃娃
哈哈
运行结果:
Process finished with exit code 0
那么可能有同学会问,先读不就好了么?
错。理由:w+ 模式下, 一开始读取不到数据,然后写的时候再将原来的内容清空,所以这种操作方式很少用。
追加读(a+)
a+模式下,不论先读还是后读,都是读取不到数据的。
f = open("⼩娃娃", mode="a+", encoding="utf-8")
f.write("麻花藤")
content = f.read()
print(content)
f.flush()
f.close()
运行前的文件:小娃娃
爱笑的眼睛
运行后的文件
爱笑的眼睛麻花藤
运行结果:
Process finished with exit code 0
还有一些其它带b的操作,就不多赘述了,就是把字符换成字节,仅此而已。
其它相关操作
seek(n)
光标移动到n位置,注意,移动的单位是byte,所以如果是utf-8的中文部分要是3的倍数。
通常我们使用seek都是移动到开头或者结尾。
移动到开头:seek(0) 。郑州人流价格 http://www.zzzykdfk.com/
移动到结尾:seek(0,2),seek的第一个参数表示的是从哪个位置进行偏移,默认是0,表示开头,1表示当前位置,2表示结尾。
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
f.flush()
f.close()
运行前的文件:小娃娃
123456789
运行后的文件:小娃娃
张国荣
运行结果:
123456789
Process finished with exit code 0
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()
运行前的文件:小娃娃
123456789
运行后的文件:小娃娃
123456789
9
Process finished with exit code 0
truncate()
截断文件光标后的内容,日常操作过程中几乎不用。
f = open("小娃娃", mode="w", encoding="utf-8")
f.write("哈哈") # 写⼊两个字符
f.seek(3) # 光标移动到3, 也就是两个字中间
f.truncate() # 删掉光标后⾯的所有内容
f.close()
运行前的文件:小娃娃
麻花藤最爱的人
运行后的文件
哈
运行结果:
Process finished with exit code 0
深坑请注意:在r+模式下,如果读取了内容,不论读取内容多少,光标显示的是多少,再写入或者操作文件的时候都是在结尾进行的操作。
所以如果想做截断操作,记住了,要先挪动光标,挪动到你想要截断的位置,然后再进行截断关于truncate(n), 如果给出了n. 则从开头开头进行截断,如果不给n,则从当前位置截断,后面的内容将会被删除。
修改文件以及另一种打开文件的方式
import os
with open("⼩娃娃", mode="r", encoding="utf-8") as f1, \
open("⼩娃娃_new", mode="w", encoding="UTF-8") as f2:
content = f1.read()
new_content = content.replace("冰糖葫芦", "⼤⽩梨")
f2.write(new_content)
os.remove("⼩娃娃") # 删除源⽂件
os.rename("⼩娃娃_new", "⼩娃娃") # 重命名新⽂件
弊端:一次将所有内容进行读取,导致内存溢出,解决⽅案: 一行一行的读取和操作。
import os
with open("⼩娃娃", mode="r", encoding="utf-8") as f1, \
open("⼩娃娃_new", mode="w", encoding="UTF-8") as f2:
for line in f1:
new_line = line.replace("⼤⽩梨", "冰糖葫芦")
f2.write(new_line)
os.remove("⼩娃娃") # 删除源⽂件
os.rename("⼩娃娃_new", "⼩娃娃") # 重命名新⽂件
另外有需要云服务器可以了解下创新互联cdcxhl.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。