一、文件介绍
文件是操作系统的文件系统模块提供给用户或应用程序用于操作硬盘的数据存储单元,是计算机存储数据的基本单位,可以通过文件实现对硬盘的读取。日常工作中我们经常使用文本编辑器,如记事本、word等进行文件的读写操作。本文中我们将重点介绍如何通过代码进行文件操作,当然Python也为我们提供了操作文件的功能。
二、文件的基本操作
文件的三大操作步骤依次是,打开文件、读写文件、关闭文件。
2.1、打开文件
Python提供了一个open()功能用于打开操作系统的文件。打开文件有两大类模式,第一类是控制文件读写操作的模式。
- r : 只读模式
- w : 只写模式,如果文件有内容,它会先清空再写。
- a : 只追加写模式,如果文件有内容,它在原内容末尾后追加写入
- + : 不能单独使用,可以 r+、w+、a+。在原有的基础上增加功能,这三种模式都是可读科协,但是会受限于原有功能
第二大类模式是控制文件读写内容的模式
- t模式 : 默认的模式,读写以字符串为单位。只针对文本类型的文件。
- b模式 : 二进制模式,可以用来操作图片、视频等二进制文件
这两大列模式不能单独使用,必须配合使用。接下来我们看open()是怎么打开文件的。
def open(file, mode='r', buffering=None, encoding=None, errors=None, newline=None, closefd=True):
这个就是open()的函数原型。先来看第一个参数file,它指的是传入的文件路径,这里可以是相对路径也可以是绝对路径。第二个参数就是我们前面提到的模式,可以看到他默认是以读模式打开文件,前边我们还说了默认读写内容的模式是文本文件。这个功能会返回一个文件对象,也可以理解为返回一个新的数据类型。第一个需要我们关注的参数是encoding,它的默认值为None,就是说它默认是按照操作系统的编码打开文件。这里我们一般会指定为utf-8。
2.2、读取文件
读取文件通过文件对象的read()功能实现的, read()的返回值就是文件的内容。如果我们以t模式打开的文件,那它的返回值就是字符串,如果以b模式打开,那它的返回值就是二进制数据。
2.3、关闭文件
我们在打开一个文件是,涉及两方面的资源。一方面是变量f所占的内存空间,这里可以通过del解除绑定。第二个就是操作系统打开的具体文件占用的内存空间。 这个资源也需要释放,就需要调用close()功能关闭这个文件。
2.4、文件操作演示
前边我们知道了文件的操作流程,先打开文件,然后进行读取,读取完成进行文件关闭。下边我们来演示一下这个流程, 首先创建一个文件,在文件中写入字符,例如a.txt
f = open('a.txt', mode='rt', encoding='utf-8')
res = f.read()
print(res)
f.close()
如上所示,这个代码文件的结果,就是打印了a.txt中的文本内容。这个mode参数默认就是rt模式,也可以不写。
2.5、with上下文管理
在文件操作的三大步骤中,关闭文件总是容易被遗忘,导致操作系统的资源一直被占用。针对此现象Python提供了一种更加友好的操作文件的方式,通过这种方式就不用主动去关闭文件了,Python会自动帮助程序进行关闭,这就是with语法,也称之为上下文管理器。
with open('a.txt', mode='rt', encoding='utf-8') as f:
res = f.read()
print(res)
如上代码所示,我们就使用with语法执行了文件的基本操作。with语法还可以同事打开多个文件。
with open('a.txt', mode='rt', encoding='utf-8') as f1, \
open('b.txt', mode='rt', encoding='utf-8') as f2:
res = f1.read()
print(res)
这里的\表示续行的意思,一行代码太长了,不利于阅读,这时候就可以使用\进行续行,python还是会理解这是一行代码。
三、文件操作模式
前边我们说了文件有两大类模式,现在分别对各种模式进行详细的讲述。我们先看读写模式 r、w、t。在使用读写模式时,先默认文件内容使用t模式。因为对文本文件读写和二进制文件读写类似的,我们拿常用的文本文件演示即可。后续再单独描述二进制文件。
3.1、r模式
r模式是只读模式。在r模式下,如果打开的文件不存在会报错:
with open('c.txt', mode='rt', encoding='utf-8') as f:
pass
# ...
## 执行结果:
Traceback (most recent call last):
File "/Users/wangfujie/Documents/code/python/teach/test.py", line 2, in <module>
with open('c.txt', mode='rt', encoding='utf-8') as f:
FileNotFoundError: [Errno 2] No such file or directory: 'c.txt'
如上所示,如果文件不存在,会报错FileNotFoundError。示例代码中的pass是什么也不做的意思,也可以理解为占位符。 …和pass是一样的效果。如果文件存在,文件指针会处于最开始的位置。
3.2、文件指针
这里我们提到一个概念文件指针,这里的指针并不是C/C++中的指针。是指打开文件后要操作字符的位置,r模式下打开文件文件指针处于开头。也就是说这时候如果用read()读取字符将从第一个字符开始读取。
with open('a.txt', mode='rt', encoding='utf-8') as f:
print(f.read())
print(f.read())
print('-----------')
## 执行结果
你好
-----------
从这个示例中我们看出,第一次读取read()从第一个字符读取到文件末尾。这时候指针已经调到了文件末尾,所以第二次读取是空数据。
3.3、w模式
w模式是只写模式。在w模式下,如果打开的文件不存在会创建这个文件。如果文件存在,w模式会清空文件内存,然后文件指针处于开始位置。
with open('a.txt', mode='wt', encoding='utf-8') as f:
f.write('你好吗\n')
f.write('你也好\n')
这段代码的运行结果就是a.txt文件改写为了 ‘你好吗\n你也好’。文件打开会被清空内容,文件指针处于其实文件,第一次写入后文件指针停留在当前文件末尾,第二次写入在当前文件末尾继续添加内容。
2.4、a模式
a模式是只追加写模式,它也是只能写不能读。和w模式一样,如果文件不存在也会创建文件,文件指针处于开始位置。但是如果文件存在,它就会打开文件并且文件指针处于文件的末尾。a模式下打开文件不会清空文件内容。这里不再做代码演示,请读者自行测试。
2.5、+模式
+模式不能单独使用,必须配合r、w、a模式结合使用,它给r、w、a模式赋予可读可写的功能,同时他也受限于r、w、a。我们先看r+
with open('c.txt', mode='r+t', encoding='utf-8') as f: # mode='rt+'效果是一样的
pass
## 执行结果:
FileNotFoundError: [Errno 2] No such file or directory: 'c.txt'
虽然 r+模式是可读可写,但是以r为准,文件不存在一样会报错。如果文件存在,打开文件进行写入,会在文件开始出写,因此新打开的文件指针位于开头,并且会覆盖已有内容。
接下来看w+模式
with open('a.txt', mode='w+t', encoding='utf-8') as f:
f.write('abc\n')
f.write('123\n')
print(f.read())
w+模式在打开文件时,一样会清空文件,在写入两行数据后,read()是读取不到内容的,因此文件指针是位于文件末尾处的。
最后说一下a+模式,也是以a为准,如果文件不存在就会创建文件。文件存在指针会跳到文件末尾,虽然可读可写,也是读不到数据的。
2.6、 x模式
x模式也是只写模式,它和w模式的区别是,w模式如果文件不存在就创建文件,文件存在就清空文件。x模式是文件不存在就创建,文件存在就报错。
with open('a.txt', mode='xt', encoding='utf-8') as f:
pass
# 执行结果
FileExistsError: [Errno 17] File exists: 'a.txt'
2.7、b模式
前边示例我们都使用的t模式,它读写以字符串为单位,因此读写涉及编码解码过程。如果要读取图片文件或视频文件,仍然使用t模式读取的话,打开文件不会报错,但是读取就会报错了,它会把二进制尝试按照UTF-8进行解码,就会报解码错误。这时候我们就要使用b模式了。b模式并不是只能打开二进制文件,也可以打开文本文件,因为所以文件存储到磁盘都是二进制。
with open('a.txt', mode='rb') as f: # 这里不能加encoding参数
res = f.read()
print(res, type(res))
# 执行结果
b'\xe4\xbd\xa0\xe5\xa5\xbd' <class 'bytes'>
这里read()是原封不到把磁盘的二进制读取出来了,a.txt使用UTF-8存储了两个汉字,我们知道UTF-8存储一个汉字是3个字节,因此打印出来是6个字节。这里Python为了显示方便,给换了十六进制进行打印。数据类型使用bytes类型。
接下来看一下通过b模式写文件
with open('a.txt', mode='wb') as f: # 这里不能加encoding参数
f.wirte('你好'.encode('utf-8'))
这里必须通过编码为二进制数据才可以写入,直接写入字符串会报错。
四、回车与换行符
在古老的打字机时,在打印一行后需要换行,需要加两个字符,一个是回车return,return是回到该行的行首,用\r表示。一个是换行newline,进入到下一行,用\n表示。也就是使用\r\n来表示换行。为了节省空间,不同平台进行了不同的精简,有的平台使用\r表示换行,有的平台使用\n表示换行,现在依然存在此差异。例如windows使用\r\n表示回车+换行,linux用\n表示回车加换行。
但是在python3中做了优化,统一使用\n表示回车+换行,运行在windows平台时,它会自动转换为\r\n。
五、文件对象可迭代
使用open()打开一个文件后,得到一个文件对象,这个文件对象也是可迭代对象,也就是说可以使用for循环。每次迭代时,f 读取一行内容(包括 \n)。
with open('a.txt', mode='rt') as f:
for line in f:
print(line)
「真诚赞赏,手留余香」
真诚赞赏,手留余香
使用微信扫描二维码完成支付
