Day14 文件光标的移动及文件数据的修改
文章目录
- Day14 文件光标的移动及文件数据的修改
- 1、文件内光标的移动
- 1.2、控制光标的移动 seek(offset,whence)
- 2、文件内数据修改
- 2.1、覆盖写
- 2.2、重名写
- 3.1、函数简介
- 作业
- 1、尝试着将今日作业第二题注册、登录功能封装成函数
- 注册函数
- 登录函数
- 使用
1、文件内光标的移动
- 在文本模式下 read()括号内输入的参数为几就是读几个字符
with open(r'user.txt', 'a', encoding='utf_8')as write_1, open(r'user.txt', 'r', encoding='utf_8')as read_1:
print(read_1.read(2))
>>>
ab
- 在二进制模式下,read()括号内输入的参数是几就是几个字节
with open(r'user.txt','rb')as read_2:
print(read_2.read(2))
>>>
b'ab'
- tell()返回的永远是字节,获取光标从头开始移动了多少个字节
with open(r'user.txt','r',encoding='utf')as read_2:
print(read_2.read(3))
print(read_2.tell())
>>>
abc
3
1.2、控制光标的移动 seek(offset,whence)
offset::控制光标的移动量(字节)(可以使用负数往回移)
whence:
0:从文件开头位置开始
with open(r'user.txt','r',encoding='utf')as read_2:
print(read_2.read(3))
read_2.seek(1,0)
print(read_2.read())
>>>
abc
bc你好
1:从光标现在的位置开始 (文本模式无法使用)
with open(r'user.txt','rb')as read_2:
print(read_2.read(3).decode('utf'))
read_2.seek(3,1)
print(read_2.read().decode('utf'))
>>>
abc
好
2:从文件末尾的位置开始 (文本模式无法使用)
with open(r'user.txt','rb')as read_2:
print(read_2.read().decode('utf8'))
read_2.seek(-5,2)
print(read_2.read().decode('utf8'))
>>>
abc你好
好
1和2只能在二进制模式下使用
2、文件内数据修改
机械硬盘存储数据的原理
1、数据的而修改,其实是覆盖写
2、数据删除,占有态变为自由态
代码修改文件的方式
2.1、覆盖写
先将文件内容读到内存,在内存中完成修改,之后直接利用w模式将其写入
with open(r'user.txt', 'r', encoding='utf_8')as read_1:
data = read_1.read()
new_data = data.replace('a', '鸡')
with open(r'user.txt', 'w', encoding='utf_8')as write_1:
write_1.write(new_data)
优点:硬盘只会占用一块空间
缺点:数据量较大的时候会造成内存溢出
2.2、重名写
先读取文件内容到内存,在内存中完成修改,之后保存到另一个文件中,再将原文件删除,将新的文件重命名为原文件
import os
with open(r'user.txt', 'r', encoding='utf_8')as read_1,open(r'.user.txt.sap', 'w', encoding='utf_8')as write_1:
for i in read_1:
write_1.write(i.replace('b','哥'))
os.remove('user.txt')
os.rename('.user.txt.sap','user.txt')
优点:不会造成内存溢出
缺点:有那么一段时间需要占用硬盘两个地方,也可能只是再内存中创建传入硬盘
3.1、函数简介
函数与循环的区别
- 循环是在相同的位置反复执行相同的代码
- 函数是在不同的位置执行相同
def numberone(c,p): # def 是创建函数的关键字 括号内是函数的参数
'''求和函数,求两个数之间的和
第一个参数是两个数中小的值,第二个是大的那个值'''
p+=1
data_1=0
for i in range (c,p):
data_1+=i
return data_1 # 返回值
print(numberone(1, 100)) #调用函数
>>>
5050
作业
1、尝试着将今日作业第二题注册、登录功能封装成函数
注册函数
def reg_user(reg_name, reg_password, path_user):
'''
一个用户账号密码的注册函数,账号不允许重复
注册输入的用户名:param reg_name:
注册输入的密码:param reg_password:
注册的账户存入的路径(字符串):param path_user:
:return: boll值
'''
with open(r'%s' % path_user, 'a', encoding='utf-8')as user_write, open(r'%s' % path_user, 'r',
encoding='utf')as user_read:
for user_str in user_read:
# 切割字符串装入列表,这里只判断账号 不需要清除尾部换行空格
user_list = user_str.split('|')
if reg_name == user_list[0]:
result = False
break
else:
reg_user = '|'.join((reg_name, reg_password))
user_write.write(f'{reg_user}\n')
user_write.flush()
print(user_read.read())
result = True
return result
登录函数
def log_in(login_name, login_password, path_read):
'''
基于reg_user配套使用的登录函数,
用户输入的登录账号:param login_name:
用户输入的登录密码:param login_password:
用户的账户库:param path_read:
:return: bool值
'''
with open(r'%s' % path_read, 'r', encoding='utf')as user_read:
print('用户登录'.center(40, '-'))
for i in user_read:
user_list = i.strip().split('|')
if login_name == user_list[0]:
if login_password == user_list[1]:
result = True
break
else:
result = False
return result
使用
while True:
item = input('1.注册\n2.登录\n0.退出\n请输入:')
if item == '1':
while True:
user_name = input('请输入您的账号:').strip()
user_password = input('请输入您的密码:').strip()
if reg_user(user_name, user_password, 'userinfo.txt'):
print('注册成功')
break
else:
print('账号已存在,请重试')
continue
elif item == '2':
while True:
user_name = input('请输入您的账号:').strip()
user_password = input('请输入您的密码:').strip()
if log_in(user_name, user_password, 'userinfo.txt'):
print('登录成功')
break
else:
print('账号或密码错误')
continue
elif item == '0':
print('系统已退出')
break
else:
print('无此选项')