目录
一、文件操作
1、概念讲解
首先我们要知道文件是操作系统暴露给用户的快捷方式,当我们使用的时候只需要双击就能将文件读取到内存中运行,使用ctrl+s就可以将文件保存到硬盘中,这些对文件进行修改或使用的动作就是文件操作,除了借助操作系统,我们可以使用python代码进行这一系列的操作。
2、通过代码打开文件的两种方式
方式一:
f.open(文件路径,文件读写模式,encoding='文件编码类型(默认情况下为utf8)')
f.close()
特点:一次只能打开一个文件,使用完文件后需要输入f.close关闭文件,但是如果忘记关闭文件并不会有提示。
方法二:
with open(文件路径,文件读写模式,encoding='文件编码类型(默认情况下为utf8)') as f1,open(文件路径,文件读写模式,encoding='文件编码类型(默认情况下为utf8)') as f2:
with条件下的操作代码
特点:当我们使用with方法打开文件的时候,可以一次性打开多个文件并且不需要输入close方法,会自动运行close方法。
一些小知识点总结:
①当我们在使用代码打开文件的时候,如果填写的文件路径中有撬棍符号(\)的时候,我们需要在路径文本的前面加上一个r。为了防止漏写,我们可以在每个路径前面都加上r,免去判断的过程。
②在我们选择文件的读写模式的时候,通常写的都是简写,他们的全称分别是:rt、wt、at。
③当我们打开文件暂时不知道需要做什么的时候可以使用pass和...来跳过并保证代码通畅运行,但是在使用过程中通常都写pass,三个点怕在检查的时候看不清。
④当我们在写入的时候,需要注意换行符的使用,如果不加入换行符会一直在同一行书写,直到那一行写满才会换行。
二、文件的读写模式
这里的读写模式只针对文本文件,其他类型的文件需要专属的软件才能打开。对于文本文件有三种读写模式:只读模式(r)、只写模式(w)、只追加模式(a)。
1、只读模式(r)
在只读模式下我们只能读取文本中的内容不能修改。
当我们使用只读模式打开文件的时候如果文件不存在会报错,如果存在就正常打开。
with open(r'D:\pythonproject\a.txt','r',encoding='utf8') as f1:
a = f1.read()
print(a) # 结果:这是a文本
2、只写模式(w)
在只写模式下打开文件会清空其中的内容,然后写入我们需要写入的内容,通常来说在开发程序的时候用的都是只写模式,需要我们生成第一手代码。但是在只写模式下我们不能进行读取的动作。
当我们使用只写模式打开文件的时候如果文件不存在会创建新文件,如果存在就清空内容然后写入。
with open(r'D:\pythonproject\a.txt','w',encoding='utf8') as f1:
a = f1.write('猪猪男孩小康康')
with open(r'D:\pythonproject\a.txt', 'r', encoding='utf8') as f2:
b = f2.read()
print(b) # 结果:猪猪男孩小康康
3、只追加模式(a)
在只追加模式下我们同样不能读取文本的内容,当我们在往文件内写入内容的时候,会在文件的末尾插入我们缩写的内容。
当我们用只追加模式打开文件的时候如果文件不存在会创建一个新的文件,如果文件存在就会在末尾加入缩写的内容。
with open(r'D:\pythonproject\a.txt','a',encoding='utf8') as f1:
a = f1.write('猪猪男孩小康康')
with open(r'D:\pythonproject\a.txt', 'r', encoding='utf8') as f2:
b = f2.read()
print(b) # 结果:这是a文本猪猪男孩小康康
三、文件的操作模式
上文中我们讲解的文本的读写模式只是操作模式中的一种,也是默认的操作模式,在输入读写模式的时候只需要简写就可以。这里我们还要介绍通用的操作模式——二进制模式。为了方便理解我们把t模式(文本操作模式)和b模式(二进制操作模式)对比着讲解:
t模式 | b模式 |
---|---|
默认的操作模式 | 二进制操作模式 |
三种操作模式的全称是rt、wt、at,当我们使用的时候可以省略t | 对应的三种模式是rb、wb、ab,使用的时候需要写全 |
只能对文本文件进行操作 | 可以对所有类型的文件进行操作,但是部分类型的文件不能打开 |
操作的时候可以指定的个数,是字符的个数 | 操作的时候可以指定操作的个数,这里是字节的个数(一个英文一个字节,一个中文三个字节) |
需要在后面指定编码的类型(encoding = 'utf8') | 不需要在后面指定编码类型(已经是二进制了) |
注:二进制操作模式下的各种规律是和文本操作模式下一样的,可以参考上面的例子。
四、文件的诸多方法
1、read()
把文件中的所有内容一次性读取出来,括号内可以加入参数控制一次读取多少数据值,但是在不同的操作模式下有不同的读取规律。当文件过大的时候容易出现内存溢出的情况,因此有了以下读取方式:
for line in document:
print(line)
通过for循环一行行读取内容,防止出现内存溢出的情况。
with open(r'D:\pythonproject\a.txt', 'r', encoding='utf8') as f6:
print(f6.read())
# 结果如下:
'''
小康康爱睡觉
小康康爱洗澡
小康康爱干饭
'''
2、readline()
执行一次会读取一行的内容,和for循环功能相似,但是需要重复执行。
with open(r'D:\pythonproject\a.txt', 'r',encoding='utf8') as f4:
a = f4.readline()
b = f4.readline()
c = f4.readline()
print(a)
print(b)
print(c)
# 结果如下:
'''
猪猪男孩小康康1
猪猪男孩小康康2
猪猪男孩小康康3
'''
3、readlines()
一次性读取所有的文件内容,并把他们以一行为一个数据值分开,放入列表中。
with open(r'D:\pythonproject\a.txt', 'r',encoding='utf8') as f4:
a = f4.readlines()
print(a)
# 结果如下:
'''
['猪猪男孩小康康1\n', '猪猪男孩小康康2\n', '猪猪男孩小康康3']
'''
4、write()
写入内容
with open(r'D:\pythonproject\a.txt', 'w',encoding='utf8') as f5:
a = f5.write('小康康爱睡觉')
with open(r'D:\pythonproject\a.txt', 'r', encoding='utf8') as f6:
print(f6.read())
# 结果如下:
'''
小康康爱睡觉
'''
5、writelines()
在括号内可以插入一个列表,之后会将列表中的数据值一个个都写入到文本中
with open(r'D:\pythonproject\a.txt', 'w',encoding='utf8') as f5:
a = f5.writelines(['小康康爱睡觉\n','小康康爱洗澡\n','小康康爱干饭\n'])
with open(r'D:\pythonproject\a.txt', 'r', encoding='utf8') as f6:
print(f6.read())
# 结果如下:
'''
小康康爱睡觉
小康康爱洗澡
小康康爱干饭
'''
6、readabel()
用于判断文件是否可以读取
with open(r'D:\pythonproject\a.txt', 'r',encoding='utf8') as f4:
a = f4.readable()
print(a)
# 结果如下:
'''
True
'''
with open(r'D:\pythonproject\a.txt', 'w',encoding='utf8') as f5:
a = f5.readable()
print(a)
# 结果如下:
'''
False
'''
7、writable()
用于判断文件是否可以写入
with open(r'D:\pythonproject\a.txt', 'r',encoding='utf8') as f4:
a = f4.writable()
print(a)
# 结果如下:
'''
False
'''
with open(r'D:\pythonproject\a.txt', 'w',encoding='utf8') as f5:
a = f5.writable()
print(a)
# 结果如下:
'''
True
'''
8、flush()
强制保存的作用
9、tell
返回光标所在位置的函数,他可以返回光标距离开头的字节数。
with open(r'D:\pythonproject\a.txt', 'r',encoding='utf8') as f4:
a = f4.read()
# 先让光标跑到末尾然后返回距离开头的位置
b = f4.tell()
print(a)
print(b)
# 结果:
'''
猪猪男孩小康康
21
'''
五、文件内光标的移动
在上面尝试文件的操作模式的相关内容的时候我们会发现有些代码第一次执行有内容读取到,后面就读取不到内容了,这是因为光标在第一次读取后就到了文件的最末尾,之后的几次读取就没有内容可以读取了。
接下来我们介绍一个函数用于改变光标的位置:
seek(offset, whence)
这里的offset参数是用来控制移动的位移量,具体的效果需要参考当前的操作模式,比如文本模式下是一个字符,二进制模式下是一个字节(bytes)
whence参数是规定使用的模式,有0,1,2三种模式,其中0模式表示基于文件开头开始操作,1模式表示在文件的当前位置进行操作,2模式表示在文件的末尾进行操作,但是位移量需要变成负数才能读到结果。在使用时候文本模式只能使用0模式,二进制模式可以使用所有模式
t模式下的操作展示:
with open(r'D:\pythonproject\a.txt', 'rt, encoding='utf8') as f2:
a = f2.read()
b = f2.read()
f2.seek(0, 0)
c = f2.read()
print('结果:'+a)
print('结果:'+b)
print('结果:'+c)
# 结果如下:
'''
结果:猪猪男孩小康康
结果:
结果:猪猪男孩小康康
'''
b模式下的操作展示:
with open(r'D:\pythonproject\a.txt', 'rb') as f3:
f3.seek(6, 0)
# 跳过六个字节(两个中文)然后读取所有内容
a = f3.read()
# 跳过六个字节(两个中文)后,在当前位置再往后跳六个字节(两个中文字符),然后读取所有的后续内容
f3.seek(6, 0)
f3.seek(6, 1)
b = f3.read()
# 光标回到开头(初始化),然后从末尾往前取六个字节(两个中文字符),再读取后续内容
f3.seek(0,0)
f3.seek(-6, 2)
c = f3.read()
# 光标回到开头(初始化),然后读取六个字节(两个中文字符)
f3.seek(0, 0)
d = f3.read(6)
print('结果:'+a.decode('utf8'))
print('结果:'+b.decode('utf8'))
print('结果:'+c.decode('utf8'))
print('结果:'+d.decode('utf8'))
# 结果如下:
'''
结果:男孩小康康
结果:小康康
结果:康康
结果:猪猪
'''
with open(r'D:\pythonproject\a.txt', 'rb') as f4:
六、作业
1.编写简易版本的拷贝工具
自己输入想要拷贝的数据路径 自己输入拷贝到哪个地方的目标路径
任何类型数据皆可拷贝
ps:个别电脑C盘文件由于权限问题可能无法拷贝 换其他盘尝试即可
copy_in = input('请输入需要拷贝的数据路径(需具体到文件名称):').strip()
# 定义一个变量获取数据来源
paste_out = input('请输入需要粘贴的数据路径(需要具体到文件名称):').strip()
# 定义一个变量获取粘贴的路径
with open(copy_in, 'rb') as f1:
# 读取需要复制的内容
copy_open = f1.read()
with open(paste_out, 'wb') as f2:
# 粘贴到对应的文件目录下,如果存在就清空后重新写入内容
f2.write(copy_open)
with open(paste_out, 'rb') as f3:
# 粘贴后查看(只能看到二进制代码)
qu = f3.read()
print(qu)
2.利用文件充当数据库编写用户登录、注册功能
文件名称:userinfo.txt
基础要求:
用户注册功能>>>:文件内添加用户数据(用户名、密码等)
用户登录功能>>>:读取文件内用户数据做校验
ps:上述功能只需要实现一次就算过关(单用户) 文件内始终就一个用户信息
拔高要求:
用户可以连续注册
用户可以多账号切换登录(多用户) 文件内有多个用户信息
ps:思考多用户数据情况下如何组织文件内数据结构较为简单
提示:本质其实就是昨天作业的第二道题 只不过数据库由数据类型变成文件
文件中创建信息的时候,一组信息需要一次换行,但是还需要最末尾加上一次回车生成一行没有内容的行。
使用readlines方法读取数据
# 使用readlines方法读取数据
# 先登陆或是注册
quit_all = True
while quit_all:
# 定义一个循环并获取指令
type_1 = input('请输入需要执行的指令(1、登陆,2、注册,3、退出程序)\n:').strip()
if type_1 == '1':
# 先输入账号密码进行判断。1
log_name = input('请输入需要登陆的账号\n:').strip()
log_pwd = input('请输入需要登陆账号的密码\n:').strip()
quit_1 = True
# 定义一个变量用于退出登陆
with open(r'D:\pythonproject\userinfo.txt', 'r', encoding='utf8') as f3:
infor_log = f3.readlines()
# 把数据库中的数据读出来,一行为一项,放入列表中(每行末尾有‘\n’)
while quit_1:
infor_r = True
# 把用户输入的信息一个个和数据库中的信息比较
for j in infor_log:
t1_n, t1_p = j.split('|')
op = False
# 定义变量判断是否信息正确
if t1_n == log_name and t1_p == log_pwd+'\n':
# 判断出用户名和密码输入正确,由于末尾有\n所以对比的时候也要加上去
op = True
break
if op:
print('登陆成功')
else:
infor_r = False
print('账号或密码错误')
quit_1 = False
# 定义变量判断信息是否正确不正确就不运行后面代码
if infor_r:
# 选择后续需要进行的操作
type_2 = input('请输入需要执行的指令(1、查看所有用户信息,2、删除用户,3、退出登陆)\n:').strip()
if type_2 == '1':
print('1')
# 查看所有用户的信息
with open(r'D:\pythonproject\userinfo.txt', 'r', encoding='utf8') as f4:
# 输出数据库中的信息
check_infor = f4.readlines()
print(check_infor)
elif type_2 == '2':
# 删除用户
del_name = input('请输入需要删除的账号\n:').strip()
del_pwd = input('请输入需要删除账号的密码\n:').strip()
del_infor_right = True
with open(r'D:\pythonproject\userinfo.txt', 'r', encoding='utf8') as f5:
delete_infor = f5.readlines()
delete_infor_i = ''
# 定义一个空的字符串存储需要删除的数据值
for k in delete_infor:
# 在上面取得数据库中的信息后开始对比输入的信息
d_n, d_p = k.split('|')
if d_n == del_name and d_p == del_pwd+'\n':
# 这里跟上面一样的原因,要加'\n'
delete_infor_i = k
# print(k)
# 数据对比正确后记住需要删的那一项的内容
if delete_infor_i == '':
del_infor_right = False
print('信息不准确')
# 如果没有匹配到就不进行 删除操作
if del_infor_right:
delete_infor.remove(delete_infor_i)
# 在原有的数据库内容的基础上一出需要删除的那部分内容
with open(r'D:\pythonproject\userinfo.txt', 'w', encoding='utf8') as f6:
# 写入删除后的内容
for o in delete_infor:
f6.write(o)
with open(r'D:\pythonproject\userinfo.txt', 'r', encoding='utf8') as f7:
q = f7.readlines()
print('删除成功')
print(q)
elif type_2 == '3':
print('成功退出')
quit_1 = False
else:
print('请输入正确的指令')
elif type_1 == '2':
# 先输入需要注册的信息,然后返回文本中对比,如果没有这个文本就在最后加上
sign_name = input('请输入需要注册的用户名\n:').strip()
sign_pwd = input('请输入想要使用的密码\n:').strip()
re_use = False
# 定义一个变量判断是否是重复出现的用户名
with open(r'D:\pythonproject\userinfo.txt', 'r', encoding='utf8') as f1:
infor_sign = f1.readlines()
# 把每行数据当成列表中的一个个项输出
for i in infor_sign:
t_n, t_p = i.split('|')
# 根据‘|’符号拆分成用户名和密码方便对比
if t_n == sign_name:
re_use = True
break
# 如果重复的名字出现了就不写入
if re_use == False:
# 当用户名没有重复的时候,就把用户名和密码记录到文本文件中
with open(r'D:\pythonproject\userinfo.txt', 'a', encoding='utf8') as f2:
sign_all = '|'.join([sign_name, sign_pwd])+'\n'
# 用户名和密码合并之后再添加
f2.write(sign_all)
print('注册成功')
with open(r'D:\pythonproject\userinfo.txt', 'r', encoding='utf8') as f0:
infor_1 = f0.readlines()
print(infor_1)
else:
print('用户名重复')
elif type_1 == '3':
print('成功退出程序')
quit_all = False
else:
print('请输入正确的指令')
使用for循环读取数据
# 使用for循环读取数据
quit_all = True
while quit_all:
# 输入指令
type_1 = input('请输入需要执行的指令(1、登陆,2、注册,3、退出程序)\n:').strip()
if type_1 == '1':
# 先输入账号密码进行判断。1
log_name = input('请输入需要登陆的账号\n:').strip()
log_pwd = input('请输入需要登陆账号的密码\n:').strip()
quit_1 = True
# 定义一个变量用于退出登陆
with open(r'D:\pythonproject\userinfo.txt', 'r', encoding='utf8') as f3:
for j in f3:
# 一行行取值并跟输入的信息进行对比
t1_n, t1_p = j.split('|')
# 定义一个变量判断信息是否正确
op = False
if t1_n == log_name and t1_p == log_pwd+'\n':
# 判断出用户名和密码输入正确就退出循环,由于文本末尾有\n所以对比的时候也要加上去
op = True
break
while quit_1:
# 定义一个循环展开登陆后的后续功能,如果没有登陆成功就运行一次进行判断然后退出去
infor_r = True
# 定义一个变量判断是否登陆成功
if op:
print('登陆成功')
else:
infor_r = False
print('账号或密码错误')
quit_1 = False
if infor_r:
# 登陆成功后选择后续需要进行的操作
type_2 = input('请输入需要执行的指令(1、查看所有用户信息,2、删除用户,3、退出登陆)\n:').strip()
if type_2 == '1':
print('1')
# 查看所有用户的信息
with open(r'D:\pythonproject\userinfo.txt', 'r', encoding='utf8') as f4:
# 用for循环把数据一个个打印出来
for x in f4:
print(x)
elif type_2 == '2':
# 删除用户
del_name = input('请输入需要删除的账号\n:').strip()
del_pwd = input('请输入需要删除账号的密码\n:').strip()
del_infor_right = True
delete_infor_i = ''
with open(r'D:\pythonproject\userinfo.txt', 'r', encoding='utf8') as f5:
# 用for循环一个个取值去跟输入的信息对比,如果有符合的内容就记住这个内容
for k in f5:
d_n, d_p = k.split('|')
if d_n == del_name and d_p == del_pwd + '\n':
# 这里跟上面一样的原因,要加'\n'
delete_infor_i = k
# print(k)
# 数据对比正确后记住需要删的那一项的内容
if delete_infor_i == '':
# 如果对比的过程中没有发现符合的需要删除的信息就不执行删除操作
del_infor_right = False
print('信息不准确')
if del_infor_right:
# 得到需要删除的信息后先取得原来的数据值然后删掉需要删除的部分再写入回去
with open(r'D:\pythonproject\userinfo.txt', 'r', encoding='utf8') as f8:
write_infor = f8.readlines()
write_infor.remove(delete_infor_i)
with open(r'D:\pythonproject\userinfo.txt', 'w', encoding='utf8') as f6:
for o in write_infor:
f6.write(o)
with open(r'D:\pythonproject\userinfo.txt', 'r', encoding='utf8') as f7:
print('删除成功')
for v in f7:
print(v)
elif type_2 == '3':
print('成功退出')
quit_1 = False
else:
print('请输入正确的指令')
elif type_1 == '2':
# 先输入需要注册的信息,然后返回文本中对比,如果没有这个文本就在最后加上
sign_name = input('请输入需要注册的用户名\n:').strip()
sign_pwd = input('请输入想要使用的密码\n:').strip()
re_use = False
# 定义一个变量判断是否是重复出现的用户名
with open(r'D:\pythonproject\userinfo.txt', 'r', encoding='utf8') as f1:
# 用for循环一行行取值并拆分进行对比,如果用户名没重复就写入
for i in f1:
t_n, t_p = i.split('|')
# 根据‘|’符号拆分成用户名和密码方便对比
if t_n == sign_name:
re_use = True
break
# 如果重复的名字出现了就不写入
if re_use == False:
# 当用户名没有重复的时候,就把用户名和密码记录到文本文件中
with open(r'D:\pythonproject\userinfo.txt', 'a', encoding='utf8') as f2:
sign_all = '|'.join([sign_name, sign_pwd])+'\n'
# 用户名和密码合并之后再添加
f2.write(sign_all)
print('注册成功')
with open(r'D:\pythonproject\userinfo.txt', 'r', encoding='utf8') as f0:
# 写入后输出现有的信息
for j in f0:
print(j)
else:
print('用户名重复')
elif type_1 == '3':
print('成功退出程序')
quit_all = False
else:
print('请输入正确的指令')