文件相关操作
1.文件操作
1.文件的概念
就是操作系统暴露给用户操作硬盘的快捷方式,双击一个文件就是将硬盘中的数据加载到内存,保存文件就是将内存中的数据刷到硬盘
2.代码打开文件的两种方式:
方式1: 不推荐,因为close关键字经常被忘记
f = open(文件路径,读写模式, encoding= 'utf8')
f.close() # 保存文件
方式2:
with open(r'a.txt', 'r', encoding='utf8')as f1:
with子代码块
方式2好处在于子代码运行结束后自动调用close方法关闭资源
"""
注意:
1.open方法第一个参数是文件路径,并且\跟一些字母组合产生特殊含义导致文件路径查找混乱,为了解决混乱可以在字符串前面加上r。
D:\a\n\t
r'D:\a\n\t'
2.with支持一次性打开多个文件:
with open() as f1, open() as f2:
子代码
"""
2.文件读写模式
1.r:只读模式:只能读不能写
1.1:文件路径不存在:会直接报错
with open (r'a.txt', 'r', encoding='utf8') as f1:
print(f1.read())
1.2文件路径存在:正常读取文件内容
with open(r'a','r', encoding='utf8') as f1:
print(f1.read())
2.w:只写模式:只能写不能看
2.1文件路径不存在:自动创建
with open(r'b.txt', 'w', encoding='utf8') as f2:
f2.write('十一过得快吗\n真快')
2.2文件路径存在:先清空文件内容,之后再写入
with open(r'b.txt', 'w', encoding='utf8') as f2:
f2.write('假期综合征\n需要尽快调整')
"""
换行符需要自己添加,并且作业中数据对比中要注意该问题存在,需要用strip关键字去掉首尾换行符之后做对比
"""
3.a:只追加模式:文件末尾添加数据
3.1文件路径不存在:自动创建(同w模式)
with open (r'c.txt', 'a', encoding='utf8') as f3:
f3.write('a模式文件路径不存在会发生什么呢')
3.2文件路径存在:自动在末尾等待追加内容
"""
关键字:pass
补全语法功能本身并无任何含义,适用于功能搭建阶段
"""
3.文件操作模式
1.文本模式(t模式):
默认的模式,我们上面写的r,w,a,都是rt,wt,at的简写。
2.只能操作文本文件
3.需要制定encoding参数,如果不知道则会采用计算机默认的编码
2.二进制模式(b模式或bytes模式)
不是默认的模式,rb,wb,ab不能简写
1.可以操作任意类型文件
2.读写都是以bytes为单位
3.不需要指定encoding参数,因为它已经是二进制模式了,不需要编码
"""
二进制模式和文本模式针对文件路径是否存在的情况规律是一样的
"""
4.文件的相关操作
1.read():一次性读取文件内容,并且目标停留在文件末尾,继续读取则没有内容。并且当文件内容比较多时,该方法可能会造成计算机内存溢出,括号内还可以写数字,在文本模式下表示读取几个字符。
with open (r'c.txt', 'r',encoding='utf8') as f:
print(f.read())
print(f.read())
print(f.read()) # r模式下执行打印三遍read()到底会执行几次呢
"""
三个print最终只执行了一次,因为一次性读取文件内容,鼠标停留在了文档末尾。
"""
2.for循环:
一次性只读一行内容,避免因为文件内存过大导致内存溢出
with open (r'b.txt', 'r',encoding='utf8') as f:
for line in f:
print(line)
"""
为什么原文件每行没有间隙,pycharm打印出来就有???
因为for循环之后line中包含了一个换行符(\n),而print()关键字本身也自带换行符,相当于每循环打印一行会有两个换行符。
"""
3.readline():一次只读一行内容,要想打印多行需要多个print()
4.readlines():一次性读取文件内容,会把每行内容当做元素组成一个列表,列表中的内容会自带换行符。
5.readable:判断文件是否具备读数据的能力
6.write():写入数据
7.writable():判断文件是否具备写数据的能力
8.writelines():接受一个列表,一次性将列表中所有的数据写入
9.flush():将内存文件中数据立刻刷到硬盘,等价于ctrl + s
5.文件内光标的移动
"""
提问:可读模式下多个print只能打印一遍文件,用什么办法可以执行几遍print就打印几遍文件?
seek()关键字:控制光标的移动
"""
with open(r'b.txt', 'r', encoding='utf8') as f:
print(f.read())
f.seek(0, 0)
print(f.read())
f.seek(0, 0)
print(f.read())
"""
seek(offset, whence)
offset是位移量
whence是模式
0:基于文件开头,文本模式和二进制模式都可以使用
1:基于当前位置,只有二进制模式可以使用
2:基于文件末尾:只有二进制模式可以使用
"""
with open(r'b.txt', 'r', encoding='utf8') as f:
print(f.read())
f.seek(5, 0) # 光标往后移动5个字节,1个字母占一个字节,1个汉字占3个字节
print(f.read())
with open(r'b.txt', 'r', encoding='utf8') as f:
print(f.read())
f.seek(4, 0) # 字母占2个字节,汉字占3个字节,无法构成一个汉字
print(f.read())
r模式下多次打印一个文件
seek()关键字
6.文件内光标移动
监测文档是否变化练习题:
import time
with open(r'a.txt', 'rb') as f:
f.seek(0, 2)
while True:
line = f.readline()
if len(line) == 0:
# 没有内容
time.sleep(0.5)
else:
print(line.decode('utf8'), end='')
7.计算机硬盘修改数据原理
硬盘写数据可以看成是在硬盘上刻字,一旦需要修改中间内容,则需要重新刻字,因为刻过得字不可能从中间分开再写。
硬盘删除数据的原理:
不是直接删除而是改变状态,灯带后续数据覆盖之后才会被真正删除。
8.文件内容修改
方式1:覆盖写:直接在文件中的某个部分讲新的内容覆盖掉原内容
关键字:replace(),里面的两个参数分别表示替换前的内容和想要替换的内容。
with open(r'a.txt', 'r', encoding='utf8') as f1:
data = f1.read()
with open(r'a.txt', 'w', encoding='utf8') as f2:
f2.write(data.replace('danny', 'jenny'))
方式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') # 重命名文件
9.作业
'''
1.编写简易版本的拷贝工具
自己输入想要拷贝的数据路径 自己输入拷贝到哪个地方的目标路径
任何类型数据皆可拷贝
ps:个别电脑C盘文件由于权限问题可能无法拷贝 换其他盘尝试即可
'''
source_path = input('请输入拷贝文件的源路径>>>:')
target_path = input('请输入拷贝文件的目标路径>>>:')
with open(r'%s' % source_path, 'rb') as f1:
data = f1.read()
with open(r'%s' % target_path,'wb') as f2:
f2.write(data)
'''
2.利用文件充当数据库编写用户登录、注册功能
文件名称:userinfo.txt
基础要求:
用户注册功能>>>:文件内添加用户数据(用户名、密码等)
用户登录功能>>>:读取文件内用户数据做校验
ps:上述功能只需要实现一次就算过关(单用户) 文件内始终就一个用户信
'''
# 基础要求
print("""
1.注册
2.登陆
""")
choice = input('请输入您的选项>>>:').strip()
if choice == '1':
user_name = input('请输入您注册的用户名>>>:').strip()
user_pdw = input('请输入您注册的密码>>>:').strip()
user_data = f'{user_name}|{user_pdw}'
with open(r'user.info(单用户).txt', 'w', encoding='utf8') as f1:
f1.write(user_data)
print(f'用户{user_name}注册成功')
elif choice == '2':
load_name = input('请输入您的用户名>>>:')
load_pwd = input('请输入您的密码>>>:')
with open (r'user.info(单用户).txt', 'r', encoding='utf8') as f2:
data = f2.read()
real_name, real_pwd = data.split('|')
if load_name == real_name and load_pwd == real_pwd:
print('登陆成功')
# 拔高练习
while True:
print("""
1.注册
2.登陆
""")
choice = input('请输入您的任务编号>>>:').strip()
if choice == '1':
user_name = input('请输入您的用户名>>>:').strip()
user_pwd = input('请输入您的密码>>>:').strip()
with open (r'userinfo(多用户).txt', 'r', encoding='utf8') as f1:
for line in f1:
if user_name == line.split('|')[0]:
print(f'用户{user_name}已注册')
break
else:
user_data = f'{user_name}|{user_pwd}\n'
with open (r'userinfo(多用户).txt', 'a', encoding='utf8') as f2:
f2.write(user_data)
print(f'用户{user_name}注册成功')
elif choice == '2':
load_name = input('请输入您的用户名>>>:').strip()
load_pwd = input('请输入您的密码>>>:').strip()
with open (r'userinfo(多用户).txt', 'r', encoding='utf8') as f3:
for line in f3: # jason|123\n
real_name, real_pwd = line.split('|')
if load_name == real_name:
if load_pwd == real_pwd.strip('\n'):
print('登陆成功')
break
else:
print('用户名或密码错误')
else:
print('请输入正确编号')