登录注册功能的优化、文件内光标的移动、文件数据的修改、函数简介、其他文件操作的读写模式
补充知识
1.r+'文件路径'的作用:为了取消撬棍与字母组合的特殊含义
2.用户输入字符串后,常常会去一个变量名给予赋值操作,当对该变量名进行操作的时候,如果想要对该字符串增加字符或取消转义,常常会使用占位符(%s)、格式化输出(.format)
3.循环数据类型的时候尽量不要修改数据类型内部的数据值个数
eg:
l1 = [1,2,3,4,5,6,7,8]
for i in l1:
l1.pop()
print(i) # i 取值1,2,3,4
print(l1) # [1, 2, 3, 4]
ps:不允许出现这种情况
作业优化
1.编写简易版本的拷贝工具
自己输入想要拷贝的数据路径 自己输入拷贝到哪个地方的目标路径
任何类型数据皆可拷贝
ps:个别电脑C盘文件由于权限问题可能无法拷贝 换其他盘尝试即可
resource_path = input("请输入你想要拷贝文件的路径>>>:").strip()
target_path = input("请输入你拷贝的文件的目标路径>>>:").strip()
with open(r'%s' % resource_path, 'rb')as f1, open(r'%s'%target_path,'wb')as f2:
for line in f1:
f2.write(line)
2.利用文件充当数据库编写用户登录、注册功能
文件名称:userinfo.txt
1.基础要求:
用户注册功能>>>:文件内添加用户数据(用户名、密码等)
用户登录功能>>>:读取文件内用户数据做校验
ps:上述功能只需要实现一次就算过关(单用户) 文件内始终就一个用户信息
1.单个用户注册功能
real_name = input("请输入你想要注册的用户名>>>:").strip()
with open(r'userinfo.txt','r',encoding='utf8') as f1:
data = f1.read()
data1=data.split('|')[0]
if data1 ==real_name:
print("用户名已经存在")
else:
real_pwd = input("请输入你注册的用户名密码>>>:").strip()
with open(r'userinfo.txt','w',encoding='utf8') as f2:
f2.write(f'{real_name}|{real_pwd}')
print("注册成功")
2.单个用户登录功能
in_name = input("请输入你的用户名>>>:").strip()
in_pwd = input("请输入你的密码>>>:").strip()
with open(r'userinfo.txt','r',encoding='utf8') as f1:
info_name,info_pwd = f1.read().split('|')
if info_name == in_name and info_pwd ==in_pwd:
print("登录成功")
else:
print("登录失败")
2拔高要求:
用户可以连续注册
用户可以多账号切换登录(多用户) 文件内有多个用户信息
ps:思考多用户数据情况下如何组织文件内数据结构较为简单
提示:本质其实就是昨天作业的第二道题 只不过数据库由数据类型变成文件
while True:
print("""
1.注册功能
2.登录功能
3.退出
""")
choice = input("请输入你的指令>>.:").strip()
if choice == '1':
add_name = input("请输入你想要注册的用户名>>>:").strip()
with open(r'userinfo.txt','r',encoding='utf8') as f1:
for line in f1:
real_name = line.split('|')[0]
if real_name == add_name:
print("用户名已存在")
break
else:
add_pwd =input("请输入你的密码>>>:").strip()
with open(r'userinfo.txt','a',encoding='utf8') as f2:
f2.write(f'{add_name}|{add_pwd}\n')
print(f'用户名{add_name}注册成功')
elif choice == '2':
in_name = input("请输入你的用户名>>>:").strip()
in_pwd = input("请输入你的密码>>>:").strip()
with open(r'userinfo.txt','r',encoding='utf8') as f1:
for line in f1:
info_name,info_pwd = line.strip().split('|')
if info_name == in_name and info_pwd == in_pwd:
print("登录成功")
break
else:
print("登录失败")
elif choice == '3':
print("欢迎下次再来")
break
else:
print("请输入正确的指令")
3.注册、登录功能封装成函数
def login():
in_name = input("请输入你的用户名>>>:").strip()
in_pwd = input("请输入你的密码>>>:").strip()
with open(r'userinfo.txt', 'r', encoding='utf8') as f1:
for line in f1:
info_name, info_pwd = line.strip().split('|')
if info_name == in_name and info_pwd == in_pwd:
print("登录成功")
break
else:
print("用户名或密码错误")
def register():
add_name = input("请输入你想要注册的用户名>>>:").strip()
with open(r'userinfo.txt', 'r', encoding='utf8') as f1:
for line in f1:
real_name = line.split('|')[0]
if real_name == add_name:
print("用户名已存在")
break
else:
add_pwd = input("请输入你的密码>>>:").strip()
with open(r'userinfo.txt', 'a', encoding='utf8') as f2:
f2.write(f'{add_name}|{add_pwd}\n')
print(f'用户名{add_name}注册成功')
while True:
print("""
+++++++++++++功能++++++++++++++++++++++++++
1.注册功能
2.登录功能
+++++++++++++++++++++++++++++++++++++++
""")
choice = input("请输入你的指令>>.:").strip()
if choice == '1':
register()
elif choice =='2':
login()
else:
print("请输入正确的指令")
文件内光标的移动
控制文件光标的移动主要有read()、seek()方法
read()方法控制文件光标的移动
read()方法在两种操作模式(t模式、b模式)用法有所不同
1.t模式(文本模式):read(n)表示读取几个字符
ps:a.txt的文件内容是:hah你在干嘛ne
eg:
with open(r'a.txt','r',encoding='utf8') as f1:
print(f1.read(3)) # hah
print(f1.read(3)) # 你在干
2.b模式(二进制模式):read(n)表示读取几个字节(英文1个字节,中文3个字节起步)
ps:a.txt的文件内容是:hah你在干嘛ne
eg:
with open(r'a.txt','rb') as f1:
data = f1.read(9)
print(data.decode('utf8')) # hah你在
print(f1.read(6).decode()) # 干嘛
ps:tell()可以获取光标的字节数(从文件内容的开头到光标距离的字节数)
eg:
with open(r'a.txt','r',encoding='utf8') as f1:
print(f1.read(6)) # hah你在干
print(f1.tell()) # 12
seek(offset,whence)方法控制文件光标的移动
1.offset指光标移动的位移量
2.whence 模式(有0、1、2模式)>>> 1和2模式只能在二进制模式下使用 0模式在t、b模式下都可以
seek(n,0/1/2) >>>当n为负数时,光标向左移动n个字节;当n为正数时,光标向右移动n个字节
2.1 -- 0模式 >>>基于文件开头往后移动n个字节的位移量(offset),然后开始读取后面的字符
eg:
with open(r'a.txt','r',encoding='utf8') as f1:
f1.seek(6,0)
print(f1.seek(6,0)) # 6
print(f1.read()) # 在干嘛ne
with open(r'a.txt','rb') as f1:
f1.seek(6,0)
print(f1.seek(6,0)) # 6
print(f1.read().decode()) # 在干嘛ne
2.2 -- 1模式 >>>基于光标当前位置移动n个字节的位移量(offset),然后开始读取后面字符
eg:
with open(r'a.txt','rb') as f1:
print(f1.read(6).decode('utf8')) # hah你
f1.seek(3,1)
print(f1.read().decode()) # 干嘛ne
with open(r'a.txt','rb') as f1:
print(f1.read(6).decode('utf8')) # hah你
f1.seek(-3,1)
print(f1.read().decode()) # 你在干嘛ne
2.3 -- 2模式 >>>基于文件末尾移动n个字节的位移量(offset),然后开始读取后面的字符
eg:
with open(r'a.txt','rb') as f1:
f1.seek(-8,2)
print(f1.read().decode()) # 你在干嘛ne
ps:a.txt的文件内容是:hah你在干嘛ne
文件内数据的修改
首先要了解机械硬盘存储数据的原理:数据的修改,其实就是覆盖写;数据的删除,涉及到占有态和自由态,当数据被删除时,该占有的内存地址被恢复成自由态。处于自由态时,其实可以通过数据恢复来找回原有被删除的数据,这提醒我们谨慎卖电子产品。为了以防信息泄露,最可靠的办法是:先删除原有数据(恢复自由态),再下载一个占满内存空间的无关信息,最后再删除这个无关信息(当不法分子恢复数据时,只能恢复我们后面下载的无关信息)
覆盖写
1.实质:先读取文件内容到内存,然后在内存中进行修改(运用字符串的内置方法),最后用w模式打开文件进行写入
2.优缺点
优点:硬盘只占用一块空间
缺点:数据量较大时,会造成内存溢出
3.实操
with open(r'a.txt','r',encoding='utf8') as f1:
data = f1.read()
data1 = data.replace('nice','bad')
with open(r'a.txt','w',encoding='utf8') as f2:
f2.write(data1)
重命名
1.实质:先读取文件内容到内存,然后在内存中进行修改,之后保存到另一个文件中,再将原文件删除,最后将新的文件重命名为原文件的名字(会导入os模块)
2.优缺点
优点:不会造成内存溢出
缺点:有那么一段时间可能需要占用硬盘两个地方的空间,也可能时在内存中创建没有,并没有刷到硬盘
3.实操
import os
with open(r'a.txt','r',encoding='utf8') as f1,open(r'b.txt','w',encoding='utf8') as f2:
for line in f1:
f2.write(line.replace('bad','nice'))
os.remove('a.txt') # 删除原文件
os.rename('b.txt','a.txt') # 重命名
函数简介
1.定义函数:函数必须遵循先定义后调用的规则。
语法结构:
def 函数名(参数1,参数2...):
函数体
return 返回值
2.函数与循环的区别
函数:在不同位置反复执行的相同代码
循环:在相同位置反复执行的相同代码
文件操作的其他读写模式
前面我们了解到了r模式、w模式、a模式、rb模式、wb模式、ab模式,其实还有r+模式、w+模式、a+模式、rb+模式、wb+模式、ab+模式
在文件读写模式中"+"的含义:open a disk file for updating (reading and writing)>>>表示既可以读又可以写
1.r+模式:读写模式
1.1 新写的内容会覆盖原文件的内容,但他不会全部覆盖完,写入几个字符就覆盖几个字符,从文件开头开始写入
1.2 写入内容后,光标会停留在写入的文件内容后面,之后读取的内容就是没有没覆盖的原内容
with open(r'a.txt','r+',encoding='utf-8') as f1:
f1.write('0000') # 0000覆盖前面4个的字符
print(f1.read()) # 读取的时0000之后的内容
2.w+模式:写读模式 >>>因为‘W’会先把文件里面的内容清空掉,再去读,读到的内容就是空
with open(r'a.txt', 'w+', encoding='utf-8') as f1:
f1.write('呜呜') # 重新写入
f1.read() # 读取的内容为空 光标在最后
3.a+模式:文件内容没有被清空,并在内容末尾追加新增的内容;文件指针默认在末尾,读取的内容为空
with open(r'a.txt', 'a+', encoding='utf-8') as f1:
f1.write('呜呜') # 追加写入
f1.read() # 空的
4.rb+模式:以二进制格式打开一个文件用于读写,文件指针将会放在文件的开头,一般用于非文本文件如图片等
5.wb+模式:以二进制格式打开一个文件用于读写,如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除;如果该文件不存在,创建新文件。一般用于非文本文件如图片等。
6.ab+模式:二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写