今日内容
文件内光标的移动
-
文本模式下
在文本模式下,光标读取的时候是按照字符来读取的。
eg:
with open(r'a', 'r', encoding='utf8') as f:
data = f.read(4)
print(data) # abc加
这里3代表是移动3个字符
-
二进制模式
在二进制模式下,光标识别进位的时候是按照字节来数的
这里根据以前的所学知识可知,英文字母是一个字节,中文是三个字节,也有其他的情况,但是很少会遇见
eg:
with open(r'a', 'rb') as f:
data = f.read(3)
print(data) # b'abc'
如果我们改一下括号里的数字为4
with open(r'a', 'rb') as f:
data = f.read(4)
print(data.decode('utf8')) # 报错;这里因为是在二进制的情况下,我们解码一下。
解释:
因为中文是3个字节,前面的abc就已经占了3个字节了,当光标再数一个的不知道怎么算,于是就会报错并提示我们。
这里会思考到,光标可以自定义移动吗?答案是:可以的。
-
seek(offset,whence)
自定义移动光标的位置
offset:控制光标前进的位置数(单位是字节)
whence:是一种模式,一共有三种模式(0,1,2)
0:光标移到开头开始
1:光标在当前位置开始
2:光标在末尾开始
eg:
with open(r'a', 'r', encoding='utf8') as f:
f.seek(3,0)
print(f.read()) # 加油,冲
解释:因为当在0模式下,前进三个字节,光标就停留在abc|加油,冲。这样一个位置,然后再运行的时候就只会输出后面的字节
offset也是可以为负数的,正负是代表方向。
-
tell
这个是光标所在位置,返回值是以字节为单位
一个空格也算一个字节
eg:
with open(r'a', 'r', encoding='utf8') as f:
f.seek(3,0)
print(f.read())
print(f.tell()) # 15,按照英文字母一个字符,中文字是三个字符
文件内数据的修改
-
原理
数据修改的原理不是断开然后再加,而是让要修改的地方模糊,然后再修改(覆盖写) 数据的删除,是由占有态变为自由态;
-
代码修改文件的方式
*1.覆盖写 先读取文件的内容,在内存中修改之后,然后利用w模式打开写入 优点:只会占一块空间,更节省内存 缺点:当数据量过大的时候,会导致内存溢出。 *2.重命名 先读取到内存,在内存中修改,然后保存到另外一个文件里 优点:不会造成溢出 缺点:会更占内存*
eg:
with open(r'a', 'r', encoding='utf8') as f:
data = f.read() # 先读取出来
new_name = data.replace('ds', 'DS') # 然后再替换掉
with open(r'a', 'w', encoding='utf8') as f:
f.write(new_name) # w模式会先删除原有的,然后再重新写进去
注意:这里是字符串,会产生新的值,所以需要重新赋值。,但是列表不会,因为列表属于可变类型
函数简介
-
理解
相当于是包装一个代码过程,如果后面相使用这代码效果的时候,就可以直接使用这个包装。这样可以节省代码量。
其实print,input,len…这些方法都是函数的内置方法
- 格式:
1.循环
在相同的位置反复执行相同的代码
2.函数
在不同的位置反复执行想同的代码
-
关键字
def
-
格式
def 函数名(参数): 执行的代码段 return(返回)
更多的文件读写模式
模式 | 操作 |
---|---|
r+ | 打开可读可写文件,该文件必须存在 |
rt+ | 打开一个文本文件,可读可写,文件必须存在 |
rb+ | 打开一个二进制文件,可读可写 |
wt+ | 打开可读可写文件,如果文件存在,先清除,再加入,如果不存在,则新建 |
wb+ | 打开一个可读可写的二进制文件,如果文件存在,先清除,再加入,如果不存在,则新建 |
ab+ | 打开一个可读可写二进制文件,存在则可读,在末尾追加,没有则新建;需要使用rewind()函数 |
今日作业
代码:
is_tage = True
# 创建一个函数
def my_find():
# 读文件并获取文件
f = open(r'userinfo.txt', 'r', encoding='utf8')
# 循环判断用户名
for line in f:
# 判断用户名是否相等
if ursername == line.split('|')[0]:
# 如果相等返回False
return False
# 循环结束,说明没有用户名存在,返回True
return True
# 创建一个函数
def my_index():
# 读文件并获取文件
f = open(r'userinfo.txt', 'r', encoding='utf8')
# 循环判断用户名
for line in f:
# 将获取的数据值以|分开,然后解压赋值
ursername, password = line.split('|')
# 判断
if user_name == ursername and user_pwd == password.strip('\n'):
# 满足返回False
return False
# 循环结束,返回True
return True
while is_tage:
print('''
1.注册
2.登录
3.退出程序''')
user_order = input('please tell me your order>>>:')
if user_order == '1':
print('欢迎来到注册页面')
ursername = input('please enter yours name>>>:').strip()
# 判断,成员运算,如果函数返回False,这里则为True,显示用户已存在,反之,则不执行。
if not my_find():
print('用户已存在')
continue
else:
password = input('please enter yours pwd>>>:').strip()
password1 = input('please confirm your password>>>:').strip()
if password != password1:
print('你的密码不正确')
break
with open(r'userinfo.txt', 'a', encoding='utf8') as f:
f.write('%s|%s\n' % (ursername, password))
print(f'用户{ursername}已注册成功')
elif user_order == '2':
print('欢迎来到登录页面')
user_name = input('please enter yours name>>>:')
user_pwd = input('please enter yours pwd>>>:')
# 调用函数,也应用到了成员运算符
if not my_index():
print('登录成功')
is_tage = False
i = input('你是否要清理数据库(y/q):')
if i == 'y':
f3 = open(r'userinfo.txt', 'r+')
f3.truncate()
print('已清理数据库,欢迎下次光临')
break
else:
print('欢迎下次光临!')
break
else:
print('用户名或者密码输入不正确')
elif user_order == '3':
print('欢迎下次光临!')
break
else:
print('未收到明确指令')