今日内容概要
- 文件操作
- 文件读写模式
- 文件诸多方法
- 文件内光标的移动
- 文件内光标的移动实战演练
- 计算机硬盘存取数据的原理
- 文件内容修改
1.文件操作
1.文件的概念
操作系统给用户操作硬盘的快捷方式
比如我们双击打开一个文件,就是把硬盘中存储的数据加载到内存中
ctrl+s(保存) 就是将内存中的数据存储到电脑硬盘中
2.代码打开文件的两种方式:
1.变量名 = open('文件路径','读/写模式',encoding = 'utf8')
# 此模式打开后可以正常运行,但是会默认一直开启文件,需要在打一行代码进行关闭
2.with open('文件路径','读/写模式',encoding = 'utf8') as 变量名:
# 此模式打开文件后,执行缩进后的子代码完成后会自动关闭文件。
# 所以我们在编写代码时一般习惯使用第二种方式方法
3.
'''
文件路径的\符号容易与Python内方法冲突,所以我们在编写文件路径的时候最好在字符串引号前面添加一个r,让路径转义,这样可以避免我们误操作,导致python报错
'''
2.文件读写模式
1.文件读写模式分为:
'r' # 只读模式,只能读取文件内容,不能进行修改
'w' # 只写模式,只能编写内容到文件内,不能看
'a' # 追加模式,在文件内容末尾添加信息
1.'r' 只读模式, 如果文件路径不存在,会直接报错
with open('b.txt','r',encoding='utf8') as c:
print(c.read())
如果文件存在,就会读取文件内的内容
with open('a.txt','r',encoding='utf8') as d:
print(d.read())
2.'w'只写模式, 如果文件路径不存在,那么会创建一份新的文件
with open('b.txt','w',encoding='utf8') as c:
c.write('我是天下第一大帅哥')
# 会自动创建一个b.txt文件,并且在文件内写入 '我是天下第一大帅哥'
'''
如果需要编写多行,需要自己添加换行符,并且在后续文件对比时也要注意换行符的存在
w模式每次打开文件会先清空文件内容,然后在进行编写
'''
3.'a' 只追加模式,只在文件末尾添加数据,如果文件路径不存在,那么会创建一份新的文件
with open('a.txt','a',encoding = 'utf8') as b:
b.write('是的你真帅')
# 会在文件内容尾部添加是的你真帅
4.pass
pass 在python中的作业是为了保持语法结构的完整性
if 条件:
pass (跳过,什么都不做)
可以跳过需要执行子代码的条件/循环/...等
# pass本身没有意义
3.文件操作模式:
1.文件操作模式
1. t 文本模式
# 文本模式只能对文本类型文件进行操作
# 必须制定encoding 对应编码
# 读写是以字符为单位进行
如上述文件读写操作都是以文本模式进行的操作,我们写读写模式时把t隐藏掉了
完整的写完应该是:
with open('a.txt','rt',encoding='utf8') as b:
在读写模式后面加上t,代表我们所使用的文件操作模式
2. b 二进制模式
# 如果需要使用二进制模式需要在读写模式后面加b,这样就可以代表是二进制模式
# 可以对任意类型文件进行操作 (计算机本身就可以识别二进制)
# 读写是以bytes类型为单位
# 不需要encoding 对应编码
二进制模式的写法为:
with open('a.txt','rb') as c:
二进制模式,在'r','w','a'模式操作方式与文本模式操作方式一致
4.文件操作方法
1.read()
只读方法,一次性读取文件内所有内容,并且光标/指针停留在内容末尾。
文件内容比较多时,如果计算机内存不够读取文件内的数据,就会爆内存
read()方法中可以填数字参数
# 在文本模式表示读取几个字符
# 在二进制模式表示读取几个字节
例:
with open('a.txt','rb') as c:
print(c.read()) # 读取所有字符
with open('a.txt', 'r',encoding='utf8') as d:
print(d.read()) # 读取所有字节
2.readline()
只读一行方法:只读文件中的一行内容,并且光标/指针会停留在第一行内容末尾
with open('a.txt','r',encoding='utf8') as i:
print(i.readline()) # 我是天下第一大帅哥
print(i.readline()) # 是的你真帅
# 注意 我们在二进制模式读取时,他会有\n 换行符进行分割我们在使用readline()方法时要注意
3.readlines()
读取文件所有内容,并根据每行进行分割 # 每行都有换行符!!
with open('a.txt','r',encoding='utf8') as i:
a = i.readlines()
print(a) # ['我是天下第一大帅哥\n', '是的你真帅']
print(type(a)) # <class 'list'>
4.readable()
判断文件是否可读,返回布尔值
with open('a.txt','r',encoding='utf8') as i:
print(i.readable()) # 返回True
5.write()
写入数据
with open('a.txt','w',encoding='utf8') as c:
c.write('天下第一剑神,小白')
# a.txt 原有内容清空,并输入 '天下第一剑神,小白'
6.writable()
判断文件是否可写入内容,返回布尔值
with open('a.txt','w',encoding='utf8') as c:
print(c.writable()) # True
7.writelines()
写入一个列表,列表内可写多行内容,换行需要使用换行符隔开
with open('a.txt','w',encoding='utf8') as c:
c.writelines(["就是牛 1\n", "还是牛 2"]) # 就是牛 1 还是牛 2
8.flush()
用来刷新缓冲区的,即将缓冲区中的数据立刻写入文件,同时清空缓冲区,不需要是被动的等待输出缓冲区写入。
相当于ctrl + S 保存功能
9.for循环
for循环也可用于文件读取
在读取文件时就可以一行一行的遍历出来,这样可以避免read()方法内存容纳不下被爆掉
10.文件内光标移动
1.seek()
seek方法可以用于移动文件读取指针/光标到指定位置。
()内参数为:
offset,whence
开始的偏移量 哪里(模式0,1,2) # 模式0 从头开始 模式1,从当前光标所处位置开始 模式2 从末尾开始
with open('a.txt','rb') as c:
c.seek(3,0) # c.write('让我康康你的脸') 因为中文是三个字节
print(c.read(6).decode('utf8')) # read(6)读取偏移量0后6个字节并转码utf-8 我康
c.seek(-9,2) # 倒着取
print(c.read(9).decode('utf8')) # 你的脸
whence参数 1,2 模式只支持b(二进制模式)使用,0模式t,b模式都可以使用
# 偏移量只能是字节,不支持字符
2.tell()
tell 方法可以查询当前光标/指针所处位置 # 文本模式是字符,二进制模式是字节
a = c.tell()
print(a) # 9
5.文件内光标移动实战操作
光标移动也有实际的应用场景:
import time # 导入模块(时间)
with open(r'a.txt', 'rb') as f: # 打开文件,模式read
f.seek(0, 2) # seek()方法 偏移量0 whence 2光标移动到文件末尾处
while True:
line = f.readline() # 一行一行读取数据赋值给变量Line
if len(line) == 0: # 如果 line 的长度为0
time.sleep(0.5) # 放慢0.5秒后执行
else:
print(line.decode('utf8'), end='') # 打印光标末尾处 新增的内容
'''
此功能是一个小监控功能,可以读取文件内新录入的内容,并打印出来
'''
6.计算机硬盘修改数据的原理
1.硬盘记录数据的原理
硬盘读写数据我们可以看成在纸上记录数据,当我们需要修改中间位置内容时,就需要重新写字,写过的字不能冲中间分开它们
2.硬盘删除数据的原理
不是直接拿橡皮擦擦除纸上内容,而是改变它的状态,等待后续的文字内容覆盖它
简单的说,硬盘在保存文件时,一般会按照“簇”的形式将数据进行保存,至于保存的文件默认会记录在文件分配表中。而硬盘删除文件时,系统也不会把它所存储的文件全部清空,而是将之前在各个分配表中的“簇”标记为空显示。文件分配表里面还有哪个“簇”没有使用,后期所存储的数据也就会存入该簇中。所以在数据重新写入之前,这些删除的文件依然会存在之前所在的“簇”中,直到新数据的写入,覆盖原有数据。
我们一旦覆盖了原来已经改变状态了的区域,那么我们就无法在进行恢复了,此数据一定会丢失,无法在恢复
# 当然这是机械硬盘的原理,固态硬盘原理是由算法构成,所以就不存在恢复信息,或者由的固态硬盘会单独构建一块存储区域专供数据恢复的
7.文件内容修改
1.文件内部修改信息其实就由上述计算机硬盘修改数据的原理一致
方式1:
# 覆盖
# with open(r'a.txt', 'r', encoding='utf8') as f:
# data = f.read()
# with open(r'a.txt', 'w', encoding='utf8') as f1:
# f1.write(data.replace('jason', 'tony'))
方式2:
# 更换位置写
'''先在另外一个地方写入内容 然后将源文件删除 将新文件命名成源文件'''
import os
with open('a.txt', 'r', encoding='utf8') as read_f, \
open('.a.txt.swap', 'w', encoding='utf-8') as write_f:
for line in read_f:
write_f.write(line.replace('tony', 'kevinSB'))
os.remove('a.txt') # 删除a.txt
os.rename('.a.txt.swap', 'a.txt') # 重命名文件
8.练习题及答案
1.编写简易版本的拷贝工具
自己输入想要拷贝的数据路径 自己输入拷贝到哪个地方的目标路径
任何类型数据皆可拷贝
ps:个别电脑C盘文件由于权限问题可能无法拷贝 换其他盘尝试即可
solution:1
location = input('请输入您想要拷贝的数据路径>>>>>>:')
target_location = input('请输入您的目标数据路径>>>>>>:')
with open(r'{}'.format(location),'rb') as data: # 打开想要拷贝的数据路径地址
data1 = data.read() # 获取读取的值复制给Data1
location1 = location.split('\\')
for b in location1:
if '.' in b:
data2 = b
with open(r'{}\{}'.format(target_location,data2),'wb') as target_data: # 打开目标拷贝地址
target_data.write(data1) # 写入 data1
print('拷贝成功哦,就是牛')
solution:2
# 1.先获取用户输入信息
want_file_path = input('请输入您想要拷贝的文件路径>>>>>:')
target_file_path = input('请输入您的目标路径>>>>>>:')
# 打开文件读取所有内容
with open(r'{}'.format(want_file_path), 'rb') as file_read, open(r'{}'.format(target_file_path), 'wb') as file_write:
for data in file_read: # 遍历每一行读取的内容
file_write.write(data) # 把遍历的内容写进目标位置的新文件内部
2.利用文件充当数据库编写用户登录、注册功能
文件名称:userinfo.txt
基础要求:
用户注册功能>>>:文件内添加用户数据(用户名、密码等)
用户登录功能>>>:读取文件内用户数据做校验
ps:上述功能只需要实现一次就算过关(单用户) 文件内始终就一个用户信息
while True:
print('欢迎光临随风登录系统'
'1.用户注册:'
'2.用户登录')
choice = input('请输入您想要选择功能>>>>>>:')
if choice.strip() == '1':
print('用户注册')
with open('userinfo.txt','w',encoding='utf8') as data:
username = input('请输入您的用户名>>>>>:')
password = input('请输入您的密码>>>>>:')
data.writelines(f'{username},{password}\n')
print(f'{username}注册成功')
if choice.strip() == '2':
print('用户登录')
target_username = input('请输入用户名>>>>>:')
target_password = input('请输入密码>>>>>>:')
with open('userinfo.txt', 'r', encoding='utf8') as data1:
b = data1.readlines()
for x in b:
if target_username in x and target_password in x:
print(f'{target_username}登录成功')
else:
print('用户名或密码输入错误')
拔高要求:
用户可以连续注册
用户可以多账号切换登录(多用户) 文件内有多个用户信息
ps:思考多用户数据情况下如何组织文件内数据结构较为简单
提示:本质其实就是昨天作业的第二道题 只不过数据库由数据类型变成文件
solution:1
while True:
print('欢迎光临随风登录系统'
'1.用户注册:'
'2.用户登录')
choice = input('请输入您想要选择功能>>>>>>:')
if choice.strip() == '1':
print('用户注册')
with open('userinfo.txt','a',encoding='utf8') as data:
username = input('请输入您的用户名>>>>>:')
password = input('请输入您的密码>>>>>:')
data.writelines(f'{username},{password}\n')
print(f'{username}注册成功')
if choice.strip() == '2':
print('用户登录')
target_username = input('请输入用户名>>>>>:')
target_password = input('请输入密码>>>>>>:')
with open('userinfo.txt', 'r', encoding='utf8') as data1:
b = data1.readlines()
for x in b:
if target_username in x and target_password in x:
print(f'{target_username}登录成功')
else:
print('用户名或密码输入错误')
solution:2
while True:
print('请您根据提示输入指令\n'
'1.用户注册'
'2.用户登录'
'3.退出程序(Q)')
choice = input('请输入您想执行的功能编号>>>>>:').strip()
if choice == '1':
username = input('请输入您想要注册的用户名>>>>>:').strip()
with open(r'userinfo.txt', 'r', encoding='utf8') as data_read:
for real_data in data_read:
if username == real_data:
print('用户名已经存在,请重新注册')
break
else:
password = input('请输入你想设置的密码>>>>>:').strip()
with open(r'userinfo.txt', 'w', encoding='utf8') as data_file:
data_file.write(f'{username}|{password}')
print(f'恭喜{username}注册成功,允许登录')
elif choice == '2':
username = input('请输入您的用户名>>>>>:').strip()
password = input('请输入您的密码>>>>>:').strip()
with open(r'userinfo.txt', 'r', encoding='utf8') as data_read:
for real_data in data_read:
real_username, real_password = real_data.split('|')
if real_password == password and real_username == username:
print('登录成功')
break
else:
print('请输入正确的用户名或密码')
elif choice.upper() == 'Q':
print('程序结束')
break
else:
print('请输入正确编号')
注意:此功能并不完善,solution2 必须是在已经有userinfo.txt文件并且里面有数据才可允许
而solution1 里面无法判断用户名是否重复!!!