文件操作
- 文件操作的作用
- 文件的基本操作
- 打开
- 读写
- 关闭
- 文件备份
- 文件和文件夹的操作
1 文件操作的作用
思考:什么是文件?
下图中都是属于文件
思考: 文件操作包含什么?
答: 打开、关闭、读、写、复制….
思考: 文件操作的的作用是什么?
答: 读取内容,写入内容、备份内容….
总结: 文件操作的作用就是把一些内容(数据)存放起来,可以让程序下一次执行的时候直接使用,而不必重新制作一份,省时省力
-
文件操作步骤:
- 打开
文件对象 = open(file,访问模式)
-
操作
-
读
文件对象.read() # 写长度表示读出对应长度内容,不写长度表示读取所有 文件对象.readlines() # 已行为单位读取,每行出现的是列表中的元素 文件对象.readline() # 一次读一行
- 写
文件对象.write()
-
seek():改变文件指针
-
关闭
文件对象.close()
-
主访问模式
- w:写,文件不存在则新建该文件
- r:读,文件不存在则报错
- a:追加
-
文件和文件夹操作
- 重命名:
os.rename()
- 获取当前目录:
os.getcwd()
- 获取目录列表:
os.listdir()
- 重命名:
2 文件的基本操作
2.1 文件操作步骤
- 打开文件
- 读写等操作
- 关闭文件
注意:可以只打开和关闭文件,不进行任何读写操作
2.1.1 打开
在python,使用open
函数,可以打开一个已经存在的文件,或者创建一个新文件,语法如下:
open(name,mode)
name:
是要打开的目标文件名的字符串(可以包含文件所在的具体路径)。
mode:
设置打开文件的模式(访问模式): 只读、写入、追加等
2.1.2 文件对象方法
2.1.1.1 打开文件模式
不同模式打开文件的完全列表:
- 下面模式中但凡带
b
的都是二进制文件 - 但凡带
+
都是可读可写模式 - 文件指针相当于文件中光标的位置
模式 | 描述 |
---|---|
t | 文本模式 (默认)。 |
x | 写模式,新建一个文件,如果该文件已存在则会报错。 |
b | 二进制模式。 |
+ | 打开一个文件进行更新(可读可写)。 |
U | 通用换行模式(不推荐)。 |
r | 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。 |
rb | 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。一般用于非文本文件如图片等。 |
r+ | 打开一个文件用于读写。文件指针将会放在文件的开头。 |
rb+ | 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。一般用于非文本文件如图片等。 |
w | 打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 |
wb | 以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如图片等。 |
w+ | 打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 |
wb+ | 以二进制格式打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如图片等。 |
a | 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
ab | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
a+ | 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。 |
ab+ | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。 |
文件打开模式有很多,但是我们实际用到的就只有六种。
我们总结一下主要用到的是下面六种。
注意:
访问模式参数可以省略,如果省略则表示访问模式为 r
2.1.1.2 快速体验
写入:
# w 模式写入文件内容,如果该文件没有那么就创建一个 file
f = open("test.txt","w")
# 写入内容
f.write('aaa')
# 关闭文件句柄
f.close()
# 由于当前目录下没有 test.txt 这里就创建了一个
[15:23:02 root@dev py-demo]#ll test.txt
-rw-r--r-- 1 root root 3 Dec 27 15:23 test.txt
[15:23:08 root@dev py-demo]#cat test.txt
aaa
2.1.2 主访问模式
2.1.2.1 r 只读模式
读取报错测试:
# r 读取,如果文件不存在就报错,不支持写入操作因为表示只读
f = open('tes1t.txt','r')
# 调用 redi 函数,读取文件内容返回并 print 打印
print(f.read())
# 关闭文件句柄
f.close()
# 没有 tes1t.txt 文件所以报错
[15:29:50 root@dev py-demo]#/bin/python3 /root/py-demo/day-1/test.py
Traceback (most recent call last):
File "/root/py-demo/day-1/test.py", line 9, in <module>
f = open('tes1t.txt','r')
FileNotFoundError: [Errno 2] No such file or directory: 'tes1t.txt'
读取不报错测试:
# r 读取,如果文件不存在就报错,不支持写入操作因为表示只读
f = open('test.txt','r')
# 调用 redi 函数,读取文件内容返回并 print 打印
print(f.read())
# 关闭文件句柄
f.close()
[15:30:54 root@dev py-demo]#/bin/python3 /root/py-demo/day-1/test.py
adasdasdasdada
2.1.2.2 w 只写模式
# 只写,如果文件不存在,新建文件;执行写入,会覆盖原有内容
f = open('1.txt','w')
f.write("1231231")
f.close()
[15:34:55 root@dev py-demo]#cat 1.txt
1231231
# 只写,如果文件不存在,新建文件;执行写入,会覆盖原有内容
f = open('1.txt','w')
# 写入内容为 aaaaa ,会将上面代码写入的 1231231 内容覆盖
f.write("aaaaa")
f.close()
[15:36:27 root@dev py-demo]#cat 1.txt
aaaaa
2.1.2.3 a 追加模式
# a 追加,如果文件不存在,新建文件,不会覆盖文件原有内容
f = open('2.txt','a')
f.write('abc')
f.close()
[15:39:10 root@dev py-demo]#cat 2.txt
abc
这里我又重新编写代码,追加 123 到 2.txt 中可以看到文件内容并没有覆盖而是在当前 abc 后追加了 123
# a 追加,如果文件不存在,新建文件,不会覆盖文件原有内容
f = open('2.txt','a')
f.write('123')
f.close()
[15:39:48 root@dev py-demo]#cat 2.txt
abc123
2.1.3 读
1.为做实验先创建一个文件,如下内容
[16:13:52 root@dev py-demo]#cat test.txt
aaaaaaa
bbbbbbb
ccccccc
ddddddd
eeeeeee
read()
文件对象.read(num)
num
表示要从文件中读取的数据的长度 (单位是字节),如果没有传入num
,那么就表示读取文件中所有的数据。
读取所有:
f = open('test.txt','r')
# read 不写参数表示读取文件所有内容
print(f.read())
f.close()
[16:14:48 root@dev py-demo]#/bin/python3 /root/py-demo/day-1/test.py
aaaaaaa
bbbbbbb
ccccccc
ddddddd
eeeeeee
指定 num 读取字节长度
f = open('test.txt','r')
# read 不写参数表示读取文件所有内容
print(f.read(10))
f.close()
# 输出的时候有换行占位符 \n 占一个字节,所看到只有 9 个字母输出
[16:15:47 root@dev py-demo]#/bin/python3 /root/py-demo/day-1/test.py
aaaaaaa
bb
readlines()
readlines
可以按照行的方式把整个文件中的内容进行一次性读取,并且返回的是一个列表,其中每一行的数据为一个元素。
f = open('test.txt','r')
# 返回列表
print(f.readlines())
f.close()
[16:25:11 root@dev py-demo]#/bin/python3 /root/py-demo/day-1/test.py
['aaaaaaa\n', 'bbbbbbb\n', 'ccccccc\n', 'ddddddd\n', 'eeeeeee\n']
readline()
readline()
一次读取一行内容
f = open('test.txt')
content = f.readline()
print(f'第一行:{content}')
content = f.readline()
print(f'第二行:{content}')
f.close()
[09:42:50 root@dev py-demo]#/bin/python3 /root/py-demo/day-1/test.py
第一行:aaaaaaa
第二行:bbbbbbb
2.2 代码测试不同的访问模式
如下测试内容:
r+
:可读可写模式W+
:可读可写模式
用于测试不同访问模式之间的具体区别,并测试不同的访问模式对我们光标是否有影响
2.2.1 r+ 模式
f = open('test1.txt','r+')
f.close()
# 由于当前没有test1 这个文件所以报错
[10:24:11 root@dev py-demo]#/bin/python3 /root/py-demo/day-1/test.py
Traceback (most recent call last):
File "/root/py-demo/day-1/test.py", line 7, in <module>
f = open('test1.txt','r+')
FileNotFoundError: [Errno 2] No such file or directory: 'test1.txt'
# 当前有 test 文件不会报错
f = open('test.txt','r+')
f.close()
[09:46:38 root@dev py-demo]#/bin/python3 /root/py-demo/day-1/test.py
测试:文件指针对文件数据的影响
# 当前 test 文件内容
[10:26:32 root@dev py-demo]#cat test.txt
aaaaaaa
bbbbbbb
ccccccc
ddddddd
eeeeeee
f = open('test.txt','r+')
con = f.read()
print(con)
f.close()
[10:31:07 root@dev py-demo]#/bin/python3 /root/py-demo/day-1/test.py
aaaaaaa
bbbbbbb
ccccccc
ddddddd
eeeeeee
特点:
r+
遵循主访问模式r
的特点,如果没有文件则会报错r+
所有的 r 访问模式文件指针都是在文件开头的位置并向后读取
2.2.2 w+ 模式
w+:打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
f = open('test1.txt','w+')
f.close()
# 可以看到会自动创建一个 test1 文件
[10:35:28 root@dev py-demo]#/bin/python3 /root/py-demo/day-1/test.py
[10:36:08 root@dev py-demo]#ll test1.txt
-rw-r--r-- 1 root root 0 Dec 28 10:36 test1.txt
# 通过 w+ 读取 test 文件
f = open('test.txt','w+')
con = f.read()
print(con)
f.close()
# 可以看到当前 test 文件内容已经没有了,因为即原有内容会被删除。
[10:36:10 root@dev py-demo]#/bin/python3 /root/py-demo/day-1/test.py
[10:39:01 root@dev py-demo]#cat test.txt
特点:
w+
遵循主访问模式w
的特点,所以当没有该文件的时候就会自动创建一个新的文件w+
读取文件,文件指针在开头并会将源文件所有内容覆盖掉,即原有内容会被删除。
2.2.3 a+ 模式
打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。
f = open('test111.txt','a+')
f.close()
# test111 文件并不存在,但是执行代码并没有报错,而且新建了一个 test111 文件
[10:42:38 root@dev py-demo]#ll test111.txt
-rw-r--r-- 1 root root 0 Dec 28 10:42 test111.txt
向 test.txt
文件中写入数据
[10:44:21 root@dev py-demo]#echo "11111" > test.txt
[10:44:44 root@dev py-demo]#cat test.txt
11111
# 通过 a+ 模式读取 test数据
f = open('test.txt','a+')
print(f.read())
f.close()
# 没有读取到数据,因为 a+ 的文件指针是从文件末尾开始
[10:44:46 root@dev py-demo]#/bin/python3 /root/py-demo/day-1/test.py
特点:
a+
如果该文件不存在,创建新文件用于读写。a+
文件指针将会放在文件的结尾,无法读取数据
2.2.4 seek 函数
作用:用来移动文件指针,因为文件指针出现的位置会影响读取到的文件数据
语法如下:
文件对象.seek(偏移量,起始位置)
起始位置:
- 0:文件开头
- 1:当前位置
- 2:文件结尾
因为我们在上面的模式测试中知道,r 模式的文件指针是在文件开头,那么我想读取中间第 10 个字符该怎么办呢,这时候就需要 seek 函数;比如还有 a 模式默认文件指针是在文件结尾,所以读取不到内容也可以通过 seek ,以此类推
2.2.4.1 测试 r 模式
示例1:
1 查看 test.txt 文件当前内容
[10:46:12 root@dev py-demo]#cat test.txt
11111
f = open('test.txt','r')
# 将文件指针偏移 3 个,默认为文件开头向右偏移
f.seek(3)
print(f.read())
# 可以看到将后面两个字符读取
[10:54:12 root@dev py-demo]#/bin/python3 /root/py-demo/day-1/test.py
11
示例2:
将文件指针放到结尾通过 r 读取:
直接报错
f = open('test.txt','r+')
# 文件指针起始位置放到结尾读取
f.seek(2,2)
print(f.read())
f.close()
# 直接报错
[10:59:58 root@dev py-demo]#/bin/python3 /root/py-demo/day-1/test.py
Traceback (most recent call last):
File "/root/py-demo/day-1/test.py", line 3, in <module>
f.seek(2,2)
io.UnsupportedOperation: can't do nonzero end-relative seeks
2.2.4.2 测试 a 模式
因为我们都知道 a 模式默认的文件指针是在文件结尾,所以需要通过 seek 函数将文件指针设置为起始,从而实现读取文件内容
f = open('test.txt','a+')
# 将文件指针偏移设置为 0 ,并且从文件开头设置为起始
f.seek(0,0)
con = f.read()
print(con)
f.close()
[11:15:10 root@dev py-demo]#/bin/python3 /root/py-demo/day-1/test.py
11111
3 文件备份
需求:
用户输入当前目录下任意文件名,程序完成对该文件的备份功能(备份文件名为 xx [备份文件名为 xx[备份]后缀,例如:test[备份].txt)
其实所谓的备份就是先打开文件将源文件内容写入到目标文件中,然后再关闭文件
3.1 步骤
- 接收用户输入的文件名
- 规划备份文件名
- 备份文件写入数据
- 打开文件
- 写入数据
- 关闭文件
3.2 代码实现
1 接收用户输入目标文件名
# 接收用户输入数据
old_name = input('输入需要备份的文件名:')
2 规划备份文件
- 提取目标文件后缀
- 组织备份的文件名,xx[备份]后缀
# 2.提取文件后缀,找到用户输入的文件名中的 . 名字和后缀进行分离,文件最后面的 . 就是文件后缀
# 2.1 rfind ()方法返回字符串最后一次出现的位置的下标,从右侧寻找
index = old_name.rfind('.')
# 2.2 新名字 = 原名字 + [备份] + 后缀
# 原名字就是字符串中的一部分子串 -- 切片[开始:结束:步长]
# index 是通过 rfind 函数取出的最后一个下标位置
# 拼接得到新的文件名
new_name = old_name[:index] + '[备份]' + old_name[index:]
print(new_name)
3 备份文件写入数据
- 打开源文件和备份文件
- 将源文件写入备份文件
- 关闭文件
'''
3 备份写入数据
打开源文件和备份文件
将源文件写入备份文件
关闭文件
'''
# 打开文件
# rb,wb 模式,主要是涉及到后期的图片或者其他非文本文件内容的写入
old_f = open(old_name,'rb')
new_f = open(new_name,'wb')
# 源数据读取文件,如果不确定目标文件大写,就通过循环写入,当不在读取到数据就终止循环
while True:
# 每次读取 1024 个字节
con = old_f.read(1024)
# len(con) 判断是否为 0 ,如果为 0 表示读取完成并退出
if len(con) == 0:
break
# 将读取出来的数据写入到 new_f 中
new_f.write(con)
old_f.close()
new_f.close()
3.2.1 代码总览验证
'''
1. 接收用户输入的文件名
2. 规划备份文件名
3. 备份文件写入数据
'''
# 1.接收用户输入数据
old_name = input('输入需要备份的文件名:')
# 2.提取文件后缀,找到用户输入的文件名中的 . 名字和后缀进行分离,文件最后面的 . 就是文件后缀
# 2.1 rfind ()方法返回字符串最后一次出现的位置的下标,从右侧寻找
index = old_name.rfind('.')
'''
2.2 新名字 = 原名字 + [备份] + 后缀
原名字就是字符串中的一部分子串 -- 切片[开始:结束:步长]
index 是通过 rfind 函数取出的最后一个下标位置
拼接得到新的文件名
'''
new_name = old_name[:index] + '[备份]' + old_name[index:]
print(new_name)
'''
3 备份写入数据
打开源文件和备份文件
将源文件写入备份文件
关闭文件
'''
# 打开文件
# rb,wb 模式,主要是涉及到后期的图片或者其他非文本文件内容的写入
old_f = open(old_name,'rb')
new_f = open(new_name,'wb')
# 源数据读取文件,如果不确定目标文件大写,就通过循环写入,当不在读取到数据就终止循环
while True:
# 每次读取 1024 个字节
con = old_f.read(1024)
# len(con) 判断是否为 0 ,如果为 0 表示读取完成并退出
if len(con) == 0:
break
# 将读取出来的数据写入到 new_f 中
new_f.write(con)
old_f.close()
new_f.close()
验证:
# 创建一个test.txt 文件并写入内容
[10:50:40 root@dev py-demo]#echo '1231232132132131212313dddddddddddddddddddddddddddddddddddddddd' > test.txt
# 执行程序
[10:51:32 root@dev py-demo]#/bin/python3 /root/py-demo/day-1/test.py
输入需要备份的文件名:test.txt
test[备份].txt
# 查看结果
[10:51:53 root@dev py-demo]#cat test\[备份\].txt
1231232132132131212313dddddddddddddddddddddddddddddddddddddddd
3.3 思考
如果用户输入 .txt
,这是一个无效文件,程序如何更改才能限制只有有效的文件名才能备份?
如下代码,添加条件判断即可:
'''
1. 接收用户输入的文件名
2. 规划备份文件名
3. 备份文件写入数据
'''
# 1.接收用户输入数据
old_name = input('输入需要备份的文件名:')
# 2.提取文件后缀,找到用户输入的文件名中的 . 名字和后缀进行分离,文件最后面的 . 就是文件后缀
# 2.1 rfind ()方法返回字符串最后一次出现的位置的下标,从右侧寻找
index = old_name.rfind('.')
# 有效文件才备份,比如 .txt 就为无效文件就不再备份
# 将文件名最后一个 . 的坐标获取,然后再通过 if 判断并拿到 [index:] 最后的文件后缀给 postfix 变量
if index > 0 :
postfix = old_name[index:]
else:
print('文件格式不正确!')
#
'''
2.2 新名字 = 原名字 + [备份] + 后缀
原名字就是字符串中的一部分子串 -- 切片[开始:结束:步长]
index 是通过 rfind 函数取出的最后一个下标位置
拼接得到新的文件名
'''
# 将上面拿到的 postfix 变量重新添加到文件后缀中
new_name = old_name[:index] + '[备份]' + postfix
print(new_name)
'''
3 备份写入数据
打开源文件和备份文件
将源文件写入备份文件
关闭文件
'''
# 打开文件
# rb,wb 模式,主要是涉及到后期的图片或者其他非文本文件内容的写入
old_f = open(old_name,'rb')
new_f = open(new_name,'wb')
# 源数据读取文件,如果不确定目标文件大写,就通过循环写入,当不在读取到数据就终止循环
while True:
# 每次读取 1024 个字节
con = old_f.read(1024)
# len(con) 判断是否为 0 ,如果为 0 表示读取完成并退出
if len(con) == 0:
break
# 将读取出来的数据写入到 new_f 中
new_f.write(con)
old_f.close()
new_f.close()
# 创建 1.txt
[15:45:20 root@dev py-demo]#touch 1.txt
# 输入正确的文件
[15:45:25 root@dev py-demo]#/bin/python3 /root/py-demo/day-1/test.py
输入需要备份的文件名:1.txt
1[备份].txt
# 输入无效文件名直接报错退出程序
[15:45:30 root@dev py-demo]#/bin/python3 /root/py-demo/day-1/test.py
输入需要备份的文件名:.txt
文件格式不正确!
4 文件和文件夹的操作
在Python
中文件和文件夹的操作要借助 os
模块里面的相关功能,具体步骤如下:
1 导入 os 模块
import os
2 使用 os
模块相关功能
os.函数名()
4.1 文件重命名
os.rename(目标文件名,新文件名)
"""
1.导入 os 模块
2.使用模块功能
"""
import os
# 需要改名的文件
file = '1.txt'
os.rename(file,"2.txt")
[15:46:54 root@dev py-demo]#/bin/python3 /root/py-demo/day-1/test.py
[15:52:52 root@dev py-demo]#ls 2.txt
4.2 删除文件
os.remove(文件名)
"""
1.导入 os 模块
2.使用模块功能
"""
import os
# 当前文件路径
file = './2.txt'
os.remove(file)
[15:52:54 root@dev py-demo]#/bin/python3 /root/py-demo/day-1/test.py
[15:53:47 root@dev py-demo]#ls 2.txt
ls: cannot access '2.txt': No such file or directory
4.3 创建文件夹
os.mkdir(文件夹名称)
import os
os.mkdir("./test")
[15:53:53 root@dev py-demo]#/bin/python3 /root/py-demo/day-1/test.py
[15:57:43 root@dev py-demo]#ls test/
4.4 删除文件夹
os.rmdir(文件名)
import os
os.rmdir("./test")
[15:57:46 root@dev py-demo]#/bin/python3 /root/py-demo/day-1/test.py
[15:58:54 root@dev py-demo]#ls test
ls: cannot access 'test': No such file or directory
4.5 获取当前目录
os.getcwg()
import os
# 返回 str 数据类型
print(os.getcwd())
# 获取当前路径
[16:00:29 root@dev py-demo]#/bin/python3 /root/py-demo/day-1/test.py
/root/py-demo
4.6 改变默认目录
os.chdir(目录)
# 创建一个 aa 文件夹
[16:00:49 root@dev py-demo]#mkdir aa
import os
# 切换操作目录为当前路径下的 aa
os.chdir("./aa")
# 在 aa 目录中创建 bb
os.mkdir("bb")
[16:12:21 root@dev py-demo]#ls aa/
bb
4.7 获取目录列表
import os
# 指定获取当前目录下的 aa 文件夹
print(os.listdir('./aa'))
[16:12:21 root@dev py-demo]#/bin/python3 /root/py-demo/day-1/test.py
bb