python–文件操作(I/O):
Python 也具有操作文件(I/O)的能力,比如打开文件、读取和追加数据、插入和删除数据、关闭文件、删除文件等。
有些数据需要在程序停止后保存,就需要将数据保存到文件中。
1、什么是文件路径:
关于文件,它有两个关键属性,分别是“文件名”和“路径”。
- 文件名指的是为每个文件设定的名称。
- 路径则用来指明文件在计算机上的位置。
注意,文件夹名称和文件名在 Windows 和 OS X 上是不区分大小写的,但在 Linux 上是区分大小写的。
在 Windows 上,路径书写使用反斜杠 “\” 作为文件夹之间的分隔符。但在 OS X 和 Linux 上,使用正斜杠 “/” 作为它们的路径分隔符。
将单个文件和路径上的文件夹名称的字符串传递给它,os.path.join() 就会返回一个文件路径的字符串,包含正确的路径分隔符。
import os
print(os.path.join('nginx-1.21.1', 'nginx.exe'))
import os
myFiles = ['accounts.txt', 'details.csv', 'invite.docx']
for filename in myFiles:
print(os.path.join('C:\\demo\\exercise', filename))
C:\demo\exercise\accounts.txt
C:\demo\exercise\details.csv
C:\demo\exercise\invite.docx
2、绝对路径和相对路径:
- 绝对路径:总是从根文件夹开始,Window 系统中以盘符(C:、D:)作为根文件夹,而 OS X 或者 Linux 系统中以 / 作为根文件夹。
- 相对路径:指的是文件相对于当前工作目录所在的位置。比如:\nginx-1.22.1\conf\nginx.conf
Python os.path 模块提供了一些函数,可以实现绝对路径和相对路径之间的转换,以及检查给定的路径是否为绝对路径。
-
调用 os.path.abspath(path) 将返回 path 参数的绝对路径的字符串,这是将相对路径转换为绝对路径的简便方法。
-
调用 os.path.isabs(path),如果参数是一个绝对路径,就返回 True,如果参数是一个相对路径,就返回 False。
-
调用 os.path.relpath(path, start) 将返回从 start 路径到 path 的相对路径的字符串。如果没有提供 start,就使用当前工作目录作为开始路径。
-
调用 os.path.dirname(path) 将返回一个字符串,它包含 path 参数中最后一个斜杠之前的所有内容;
-
调用 os.path.basename(path) 将返回一个字符串,它包含 path 参数中最后一个斜杠之后的所有内容。
-
调用 os.getcwd() 将返回当前工作目录。
-
调用 os.path.split() 将同时返回目录名和文件名。
举例:
print(os.getcwd()) # D:\study\python\BaseLearn\day01\learn12
print(os.path.abspath('nginx.conf')) # D:\study\python\BaseLearn\day01\learn12\nginx.conf
print(os.path.isabs('nginx-1.21.1\\nginx.exe')) # False
print(os.path.isabs('D:\\study\\python\\BaseLearn\\day01\\learn12')) # True
print(os.path.relpath('C:\\python', 'C:\\')) # python
print(os.path.relpath('C:\\python', 'C:\\java\\images')) # ..\..\python
path = 'C:\\Windows\\System32\\calc.exe'
print(os.path.dirname(path)) # C:\Windows\System32
print(os.path.basename(path)) # calc.exe
print(os.path.split(path)) # ('C:\\Windows\\System32', 'calc.exe')
检测给定的路径是否存在,以及它是文件还是文件夹:
- 如果 path 参数所指的文件或文件夹存在,调用 os.path.exists(path) 将返回 True,否则返回 False。 参数需要是绝对路径。
- 如果 path 参数存在,并且是一个文件,调用 os.path.isfile(path) 将返回 True,否则返回 False。 参数需要是绝对路径。
- 如果 path 参数存在,并且是一个文件夹,调用 os.path.isdir(path) 将返回 True,否则返回 False。 参数需要是绝对路径。
path = 'C:\\Windows\\System32\\calc.exe'
print(os.path.exists(path)) # True
path02 = "D:\\Windows\\System32\\calc.exe"
print(os.path.exists(path02)) # False
file = 'D:\\nginx\\nginx.txt'
print(os.path.isfile(file)) # True
print(os.path.isdir(file)) # False
3、文件基本操作:
- 删除、修改权限:作用于文件本身,属于系统级操作。
- 写入、读取:是文件最常用的操作,作用于文件的内容,属于应用级操作。
print(os.remove('a.txt')) # 删除同目录下的 a.txt 文件。
文件的应用级操作可以分为以下 3 步,每一步都需要借助对应的函数实现:
- 打开文件:使用 open() 函数,该函数会返回一个文件对象;
- 对已打开文件做读/写操作:读取文件内容可使用 read()、readline() 以及 readlines() 函数;
- 向文件中写入内容,可以使用 write() 函数。
- 关闭文件:完成对文件的读/写操作之后,最后需要关闭文件,可以使用 close() 函数。
1、打开文件:
open() 函数用于创建或打开指定文件。
file = open(file_name [, mode='r' [ , buffering=-1 [ , encoding = None ]]])
- file:表示要创建的文件对象。
- file_name:要创建或打开文件的文件名称,该名称要用引号(单引号或双引号都可以)括起来。需要注意的是,如果要打开的文件和当前执行的代码文件位于同一目录,则直接写文件名即可;否则,此参数需要指定打开文件所在的完整路径。
- mode:可选参数,用于指定文件的打开模式。可选的打开模式如表 1 所示。如果不写,则默认以只读(r)模式打开文件。
- buffering:可选参数,用于指定对文件做读写操作时,是否使用缓冲区。
- encoding:手动设定打开文件时所使用的编码格式,不同平台的 ecoding 参数值也不同,以 Windows 为例,其默认为 cp936(实际上就是 GBK 编码)。一般指定为:encoding=‘utf-8’。
open 函数支持的文件打开模式:
模式 | 意义 | 注意事项 |
---|---|---|
r | 只读模式打开文件,读文件内容的指针会放在文件的开头。 | 操作的文件必须存在。 |
rb | 以二进制格式、采用只读模式打开文件,读文件内容的指针位于文件的开头,一般用于非文本文件,如图片文件、音频文件等。 | |
r+ | 打开文件后,既可以从头读取文件内容,也可以从开头向文件中写入新的内容,写入的新内容会覆盖文件中等长度的原有内容。 | |
rb+ | 以二进制格式、采用读写模式打开文件,读写文件的指针会放在文件的开头,通常针对非文本文件(如音频文件)。 | |
w | 以只写模式打开文件,若该文件存在,打开时会清空文件中原有的内容。 | 若文件存在,会清空其原有内容(覆盖文件);反之,则创建新文件。 |
wb | 以二进制格式、只写模式打开文件,一般用于非文本文件(如音频文件) | |
w+ | 打开文件后,会对原有内容进行清空,并对该文件有读写权限。 | |
wb+ | 以二进制格式、读写模式打开文件,一般用于非文本文件 | |
a | 以追加模式打开一个文件,对文件只有写入权限,如果文件已经存在,文件指针将放在文件的末尾(即新写入内容会位于已有内容之后);反之,则会创建新文件。 | |
ab | 以二进制格式打开文件,并采用追加模式,对文件只有写权限。如果该文件已存在,文件指针位于文件末尾(新写入文件会位于已有内容之后);反之,则创建新文件。 | |
a+ | 以读写模式打开文件;如果文件存在,文件指针放在文件的末尾(新写入文件会位于已有内容之后);反之,则创建新文件。 | |
ab+ | 以二进制模式打开文件,并采用追加模式,对文件具有读写权限,如果文件存在,则文件指针位于文件的末尾(新写入文件会位于已有内容之后);反之,则创建新文件。 |
file = open('aa.txt', encoding='utf-8')
print(file) # <_io.TextIOWrapper name='aa.txt' mode='r' encoding='utf-8'>
输出了 file 文件对象的相关信息,包括打开文件的名称、打开模式、打开文件时所使用的编码格式。
注意,手动修改 encoding 参数的值,仅限于文件以文本的形式打开,也就是说,以二进制格式打开时,不能对 encoding 参数的值做任何修改,否则程序会抛出 ValueError 异常。
2、open() 使用缓冲区:
通常情况下、建议大家在使用 open() 函数时打开缓冲区,即不需要修改 buffing 参数的值。
- 如果 buffing 参数的值为 0(或者 False),则表示在打开指定文件时不使用缓冲区;
- 如果 buffing 参数值为大于 1 的整数,该整数用于指定缓冲区的大小(单位是字节);
- 如果 buffing 参数的值为负数,则代表使用默认的缓冲区大小。
3、open()文件对象常用的属性:
- file.name:返回文件的名称;
- file.mode:返回打开文件时,采用的文件打开模式;
- file.encoding:返回打开文件时使用的编码格式;
- file.closed:判断文件是否己经关闭。
file = open('aa.txt', encoding='utf-8')
print(file.closed) # False
print(file.encoding) # utf-8
print(file.name) # aa.txt
print(file.mode) # r
4、读取文件数据:
读取文件中数据的操作:
- read() 函数:逐个字节或者字符读取文件中的内容;
- readline() 函数:逐行读取文件中的内容;
- readlines() 函数:一次性读取文件中多行内容。
1、read() 函数:
借助 open() 函数,并以可读模式(包括 r、r+、rb、rb+)打开的文件,可以调用 read() 函数逐个字节(或者逐个字符)读取文件中的内容。
如果文件是以文本模式(非二进制模式)打开的,则 read() 函数会逐个字符进行读取;反之,如果文件以二进制模式打开,则 read() 函数会逐个字节进行读取。
file.read([size])
file 表示已打开的文件对象;size 作为一个可选参数,用于指定一次最多可读取的字符(字节)个数,如果省略,则默认一次性读取所有内容。
f = open('aa.txt', encoding='utf-8')
print(f.read())
f.close()
黄金百战穿金甲,不破楼兰终不还。
古道黄昏瘦马,夕阳西下,小桥流水人家。
===================》
问君能有几多愁,恰是一江春水向东流。
通过使用 size 参数,指定 read() 每次可读取的最大字符(或者字节)数。
print(f.read(7)) # 黄金百战穿金甲
#以二进制形式打开指定文件,该文件编码格式为 utf-8
f = open("my_file.txt",'rb+')
byt = f.read()
print(byt)
print("\n转换后:")
print(byt.decode('utf-8'))
#关闭文件
f.close()
####################
b'Python\xe6\x95\x99\xe7\xa8\x8b\r\nhttp://c.biancheng.net/python/'
转换后:
Python教程
http://c.biancheng.net/python/
2、readline() 函数:
readline() 函数用于读取文件中的一行,包含最后的换行符“\n”。
file.readline([size])
f = open('aa.txt', encoding='utf-8')
print(f.readline()) # 黄金百战穿金甲,不破楼兰终不还。
3、readlines() 函数:
readlines() 函数用于读取文件中的所有行,它和调用不指定 size 参数的 read() 函数类似,只不过该函数返回是一个字符串列表,其中每个元素为文件中的一行内容。
f = open('aa.txt', encoding='utf-8')
print(f.readlines())
['黄金百战穿金甲,不破楼兰终不还。\n', '古道黄昏瘦马,夕阳西下,小桥流水人家。\n', '===================》\n', '问君能有几多愁,恰是一江春水向东流。']
5、向文件中写入数据:
1、write() 函数:
file.write(string)
在使用 write() 向文件中写入数据,需保证使用 open() 函数是以 r+、w、w+、a 或 a+ 的模式打开文件,否则执行 write() 函数会抛出 io.UnsupportedOperation 错误。
file = open('aa.txt', 'w', encoding='utf-8')
file.write("写入一行新的数据。")
file.close()
再次查看 aa.txt 文件,内容为:写入一行新的数据。
如果向文件写入数据后,不想马上关闭文件,也可以调用文件对象提供的 flush() 函数,它可以实现将缓冲区的数据写入文件中。
f = open("a.txt", 'w')
f.write("写入一行新数据")
f.flush()
对于以二进制格式打开的文件,可以不使用缓冲区,写入的数据会直接进入磁盘文件;但对于以文本格式打开的文件,必须使用缓冲区,否则 Python 解释器会 ValueError 错误。
2、writelines() 函数:
使用 writelines() 函数,可以轻松实现将 a.txt 文件中的数据复制到其它文件中。
f = open('aa.txt', 'r')
n = open('bb.txt','w+')
n.writelines(f.readlines())
n.close()
f.close()
需要注意的是,使用 writelines() 函数向文件中写入多行数据时,不会自动给各行添加换行符。
上面例子中,之所以 b.txt 文件中会逐行显示数据,是因为 readlines() 函数在读取各行数据时,读入了行尾的换行符。
close() 函数是专门用来关闭已打开文件的。
6、with as 上下文管理器:
使用 with as 操作已经打开的文件对象(本身就是上下文管理器),无论期间是否抛出异常,都能保证 with as 语句执行完毕后自动关闭已经打开的文件。
with 表达式 [as target]:
代码块
with open('aa.txt', 'a', encoding='utf-8') as f:
f.write("\n你好,星期六。")
# 写入一行新的数据。
# 你好,星期六。