Python关于文件操作

文件操作

创新互联专业为企业提供宁晋网站建设、宁晋做网站、宁晋网站设计、宁晋网站制作等企业网站建设、网页设计与制作、宁晋企业网站模板建站服务,十载宁晋做网站经验,不只是建网站,更提供有价值的思路和整体网络服务。

初识文件操作

使用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", "⼩娃娃") # 重命名新⽂件


当前题目:Python关于文件操作
网页网址:http://scyanting.com/article/pjdoop.html