前戏

有如下文件,但是没有相应的软件打开,想不想看?

美女模特空姐护士联系方式.txt

让你开发一个软件,可以打开此文件,你需要什么参数?

  • 文件路径: D:\美女模特空姐护士联系方式.txt
  • 编码:utf-8,gbk,gb2312….
  • 模式:只读,只写,追加,写读,读写….

使用Python来读写文件是非常简单的操作,我们使用open()来打开一个文件,获取到文件句柄,然后通过文件句柄就可以进行各种各样的操作了. 但根据打开方式的不同能够执行的操作会有相应的差异.

打开文件的方式:

  • r,w
  • r+,w+

只读模式(r)

我们先来看看这个只读操作,听名字应该也知道只能进行读不能进行别的操作

流程就是打开文件,产生一个文件句柄,对文件句柄进行相应操作,关闭文件。

1
2
3
4
5
6
7
f = open('美女模特空姐护士联系方式.txt',mode='r',encoding='utf-8')
content = f.read()
print(content)
f.close()

结果:
标题很好

open中第一个参数放入的是要打开的文件名字,第二个参数是要对这个文件进行的操作,第三参数是用什么编码方式打开文件中的内容

JRrbZt.jpg

f 可写成任意变量等,它被称作:文件句柄,文件操作符,或者文件操作对象等。
openPython调用的操作系统(windows,linux,等)的功能,而windows的默认编码方式为gbklinux默认编码方式为utf-8,所以你的文件用什么编码保存的,就用什么方法打开,一般都是用utf-8

mode为打开方式:常见的有r,w,a,r+,w+,a+等,默认不写是r

读写模式 (r+)

对于读写模式,必须是先读后写,因为光标默认在开头位置,当读完了以后再进行写入.我们以后使用频率最高的模式就是r+, 看下正确的操作:

1
2
3
4
5
6
7
8
f1 = open('../path1/小娃娃.txt',mode='r+',encoding='utf-8')
msg = f1.read()
f1.write('这支烟灭了以后')
f1.flush()
f1.close()
print(msg)
结果:
正常的读取之后,写在结尾

看下错误的操作:

1
2
3
4
5
6
7
8
f1 = open('../path1/小娃娃.txt',mode='r+',encoding='utf-8')
f1.write('小鬼')
msg = f1.read()
f1.flush()
f1.close()
print(msg)
结果:
这样写会把小鬼写在开头,并且读出来的是小鬼之后的内容

r+模式一定要记住是先读后写

r+模式坑

深坑请注意: 在r+模式下. 如果读取了内容. 不论读取内容多少, 再写入或者操作文件的时候都是在结尾进行的操作.

只写模式(覆盖写)(W)

在写文件的时候我们要养成一个写完文件就刷新的习惯. 刷新flush()

1
2
3
4
5
6
f = open('../path1/小娃娃.txt',mode='w',encoding='utf-8')
f.write('51devops.com')
f.flush()
f.close()
结果:
当我选择使用w模式的时候,在打开文件的时候就就会把文件中的所有内容都清空,然后在操作

注意点:如果文件不存在使用w模式会创建文件,文件存在w模式是覆盖写,在打开文件时会把文件中所有的内容清空.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 这个是先查看小娃娃文件中有哪些内容
f1 = open('../path1/小娃娃.txt',mode='r',encoding='utf-8')
msg = f1.read()
print(msg)

# 这个是对小娃娃文件进行覆盖写操作
f = open('../path1/小娃娃.txt',mode='w',encoding='utf-8')
f.write('51devops.edu')
f.flush()
f.close()

# 查看覆盖写后的内容
f1 = open('../path1/小娃娃.txt',mode='r',encoding='utf-8')
msg = f1.read()
print(msg)

尝试读一读

1
2
3
4
5
6
7
8
f1 = open('../path1/小娃娃.txt',mode='w',encoding='utf-8')
msg = f1.read()
print(msg)
结果:
Traceback (most recent call last):
File "D:/python_object/path2/test.py", line 563, in <module>
msg = f1.read()
io.UnsupportedOperation: not readable #模式是w,不可以执行读操作
写读模式(W+)

先将所有的内容清空,然后写入.最后读取.但是读取的内容是空的,不常用

1
2
3
4
5
6
7
f1 = open('../path1/小娃娃.txt',mode='w+',encoding='utf-8')
f1.write('小鬼')
msg = f1.read()
f1.flush()
f1.close()
print(msg)
有人说,先读在写不就行了.w+模式下 其实和w模式一样,把文件清空了,在写的内容.所以很少人用

各种读操作方法

read()

read()是将文件中所有的内容都读取

1
2
3
4
5
6
7
8
9
10
f = open('path1/小娃娃.txt',mode='r',encoding='utf-8')
msg = f.read()
f.close()
print(msg)
结果:
高圆圆
刘亦菲
张柏芝
杨紫
王菲

read()可以指定我们想要读取的内容数量

1
2
3
4
5
6
7
8
9
10
11
12
f = open('path1/小娃娃.txt',mode='r',encoding='utf-8')
msg = f.read(3) #读取三个字符
msg1 = f.read() #后边在读就会继续向后读取
f.close()
print(msg)
print(msg1)
结果:
高圆圆
刘亦菲
张柏芝
杨紫
王菲

上边现在使用的是r模式这样读取的就是文字,如果使用rb模式读取出来的就是字节  

1
2
3
4
5
6
7
8
9
f = open('path1/小娃娃.txt',mode='rb')
msg = f.read(3)
msg1 = f.read()
f.close()
print(msg)
print(msg1)
结果:
b'\xe9\xab\x98'
b'\xe5\x9c\x86\xe5\x9c\x86\r\n\xe5\x88\x98\xe4\xba\xa6\xe8\x8f\xb2\r\n\xe5\xbc\xa0\xe6\x9f\x8f\xe8\x8a\x9d\r\n\xe6\x9d\xa8\xe7\xb4\xab\r\n\xe7\x8e\x8b\xe8\x8f\xb2'

read()的弊端就是当文件很大的时候,将文件中的内容全部读取,存放在内存中这样会导致内存奔溃

readline()

readline()读取每次只读取一行,注意点:readline()读取出来的数据在后面都有一个\n

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
f = open('path1/小娃娃.txt',mode='r',encoding='utf-8')
msg1 = f.readline()
msg2 = f.readline()
msg3 = f.readline()
msg4 = f.readline()
f.close()
print(msg1)
print(msg2)
print(msg3)
print(msg4)
结果:
高圆圆
刘亦菲
张柏芝
杨紫

结果这里每个一内容中间都有一个空行是因为咱们读取的内容后边都带有一个\n print()的时候会将这个\n执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
f = open('path1/小娃娃.txt',mode='r',encoding='utf-8')
msg1 = f.readline().strip()
msg2 = f.readline().strip()
msg3 = f.readline().strip()
msg4 = f.readline().strip()
f.close()
print(msg1)
print(msg2)
print(msg3)
print(msg4)
结果:
高圆圆
刘亦菲
张柏芝
杨紫

解决这个问题只需要在我们读取出来的文件后边加一个strip()就OK了

readlines()

readlines() 将每一行形成一个元素,放到一个列表中,将所以的内容全部读出来,如果文件很大,占内存,容易崩盘。

1
2
3
4
f = open('log',encoding='utf-8')
print(f.readlines())
f.close()
# 结果['666666\n', 'fkja l;\n', 'fdkslfaj\n', 'dfsflj\n', 'df;asdlf\n', '\n', ]

如果有个较大的文件我们进行读取不推荐使用以下方法:

1
2
f = open('../path1/弟子规',mode='r',encoding='utf-8')  # 此处的../是返回到父目录
print(f.read()) #这样就是将文件一次性全部读取到内存中,内存容易奔溃

推荐使用的是这种方法:

1
2
3
4
5
6
7
8
f = open('../path1/弟子规',mode='r',encoding='utf-8')
for line in f:
print(line) #这种方式就是在一行一行的进行读取,它就执行了下边的功能
print(f.readline())
print(f.readline())
print(f.readline())
print(f.readline())
f.close()

注意点:读完的文件句柄一定要关闭

路径

相对路径

以上代码中文件名使用的是相对路径,什么是相对路径呢???

JRrLIf.jpg

如果相对还是太理解,来看下这列子:
你朋友要来找你,知道你在那个楼那一层但是不知道那个一个屋,现在你朋友来到这个楼里相对他知道的这一层然后开始找你在那个房间
这种操作就是相对路劲,例子中是通过这个楼中的这一层开始寻找,也就是相对于这个楼的某一层

绝对路径

绝对路径是从咱们电脑的磁盘开始查找,例如想要知道你的家乡是哪的,你身份证上写的住址就是绝对路径

1
2
绝对路径:从根目录下开始一直到文件名。
相对路径:同一个文件夹下面的文件,直接写文件名就可以。

我们在使用绝对路径的时候因为有\这样程序是不能识别的,解决方法:

1
2
3
4
5
open('C:\Users\Meet')  #这样程序是不识别的
解决方法一:
open('C:\\Users\\Meet') #这样就成功的将\进行转义 两个\\代表一个\
解决方法二:
open(r'C:\Users\Meet') #这样相比上边的还要省事,在字符串的前面加个小r也是转义的意思

我更推荐大家使用相对路劲,因为我把这个程序的整个文件发给你的时候,就可以运行,如果使用绝对路径还需要额外的拷贝外部文件给你

文件上下文管理器

1
2
3
with open('aa.txt', 'r', encoding='utf8') as f:
msg = f.read()
print(msg)