一、文件处理
-
1、什么是文件
文件其实是操作系统暴露给用户操作硬盘的快捷方式(接口)
-
2、为何要用文件
读写文件--------->存取硬盘
-
应用程序:open()
-
操作系统:打开文件
-
计算机硬件: 硬盘空间
-
-
3、如何用文件
打开文件:得到文件句柄并赋值给一个变量
读/写:通过句柄对文件进行操作
关闭文件
1、文件操作
"""
文件路径
相对路径与绝对路径
路径中出现了字母与斜杠的组合产生了特殊含义如何取消
在路径字符串前面加一个r
r'D:\py20\day08\a.txt'
"""
# open('a.txt')
# open(r'D:\py20\day08\a.txt')
# res = open('a.txt', 'r', encoding='utf8')
# print(res.read())
# res.close() # 关闭文件释放资源
"""
open(文件路径,读写模式,字符编码)
文件路径与读写模式是必须的
字符编码是可选的(有些模式需要编码)
"""
# with上下文管理(能够自动帮你close())
with open(r'a.txt','r',encoding='utf8') as f1: # f1=open() f1.close()
print(f1.read())
"""以后代码操作文件 推荐使用with语法"""
2、文件读写模式
"""
补全语法结构 没有实际含义
pass
...
"""
r 只读模式(只能看不能改)
# 路径不存在:直接报错
# with open(r'b.txt', 'r', encoding='utf8') as f:
# pass
# 路径存在
# with open(r'a.txt', 'r', encoding='utf8') as f:
# print(f.read()) # 读取文件内所有的内容
# f.write('123') # 写文件内容
w 只写模式(只能写不能看)
# 路径不存在:路径不存在自动创建
# with open(r'b.txt', 'w', encoding='utf8') as f:
# pass
# 路径存在:1.会先清空文件内容 2.再执行写入操作
with open(r'a.txt', 'w', encoding='utf8') as f:
# f.read()
f.write('hello world!\n')
f.write('hello world!\n')
f.write('hello world!\n')
a 只追加模式(不可读;不存在则创建;存在则只追加内容)
# a: 如果文件不存在则创建空文档,如果文件存在则清空,文件指针跳到文件末尾
f = open(r'c.txt',mode='at',encoding='utf-8')
f.write("你好啊1\n")
f.write("你好啊2\n") # 打开了文件不关闭的情况下,新写入的内容永远跟在老内容之后
f.write("你好啊3\n")
f.close()
3、文件操作方法
# 文件操作方法
# 1.读系列
with open(r'a.txt', 'r', encoding='utf8') as f:
# print(f.read()) # 一次性读取文件内所有的内容
# print(f.readline()) # 每次只读文件一行内容
# print(f.readlines()) # 读取文件所有的内容 组织成列表 每个元素是文件的每行内容
# print(f.readable()) # 判断当前文件是否具备读的能力
# 2.写系列
with open(r'a.txt','w',encoding='utf8') as f:
# f.write('克服一切困难 奥利给!') # 往文件内写入文本内容
# f.write(123) # 写入的内容必须是字符串类型
# f.writelines(['jason','kevin','tony']) # 可以将列表中多个字符串元素全部写入
# print(f.writable()) # True
# print(f.readable()) # False
f.flush() # 直接将内存内文件数据刷到硬盘 相当于ctrl+s
4、文件优化操作
with open(r'a.txt', 'r', encoding='utf8') as f:
# print(f.read()) # 一次性读取文件内所有的内容
# print(f.read()) # 一次性读取文件内所有的内容
# print(f.read()) # 一次性读取文件内所有的内容
"""
1.一次性读完之后 光标停留在了文件末尾 无法再次读取内容
2.该方法在读取大文件的时候 可能会造成内存溢出的情况
解决上述问题的策略就是逐行读取文件内容
"""
# for line in f: # 文件变量名f支持for循环 相当于一行行读取文件内容
# line
'''以后涉及到多行文件内容的情况一般都是采用for循环读取'''
5、文件操作模式
t 文本模式
1.默认的模式
r w a >>> rt wt at
2.该模式所有操作都是以字符串基本单位(文本)
3.该模式必须要指定encoding参数
4.该模式只能操作文本文件
b 二进制模式
1.该模式可以操作任意类型的文件
2.该模式所有操作都是以bytes类型(二进制)基本单位
3.该模式不需要指定encoding参数
rb wb ab
6、文件内光标的移动
# with open(r'b.txt', 'rb') as f:
# print(f.read(4).decode('utf8'))
# print(f.tell()) # 查看光标移动了多少个字节
# f.seek(3, 1)
# print(f.read().decode('utf8'))
"""
控制文件内光标的移动 f.seek()
f.seek(offset,whence)
offset表示位移量
始终是以字节为最小单位
正数从左往右移动
负数从右往左移动
whence表示模式
0:以文件开头为参考系(支持tb两种模式)
1:只支持b模式 以当前位置为参考系
2:只支持b模式 以文件末尾为参考系
"""
# 小练习:实现动态查看最新一条日志的效果
import time
with open('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('utf-8'), end='')
7、文件的内容修改
文件修改的方法从操作方式上大致可以分为两类,一种是以占用电脑内存的方式,将文件读取到内存中修改再存回硬盘;第二种方法是分别打开和新建一个文件,修改文件后写入到新的文件中,直接保存到硬盘,即占用硬盘的方式。
# 方式1 覆盖
# with open(r'c.txt','r',encoding='utf8') as f:
# data = f.read()
# # print(type(data))
# with open(r'c.txt','w',encoding='utf8') as f1:
# new_data = data.replace('tony','jason')
# f1.write(new_data)
# 方式2 新建
import os
with open('c.txt', mode='rt', encoding='utf-8') as read_f, \
open('c.txt.swap', mode='wt', encoding='utf-8') as write_f:
for line in read_f:
write_f.write(line.replace('SB', 'kevin'))
os.remove('c.txt') # 删除原文件
os.rename('c.txt.swap', 'c.txt') # 重命名文件
- 值得注意的是,用于替换的字符串字节总数(UTF-8编码中,一个英文字符占1个字节,一个中文字符占3个字节;GBK编码中,中英文都占两个字节)不得超过待替换的字符串,如果超过,就会覆盖部分原文件内容,这是由硬盘的读写机制决定的,所以,关于这一点我们在使用文件修改时,必须十分小心,及时备份,防止文件丢失。
8、二进制模式读写操作
# with open(r'a.txt','rb') as f:
# # print(f.read())
# print(f.read(6).decode('utf8'))
# with open(r'a.txt','r',encoding='utf8') as f:
# print(f.read())
# print(f.read(4))
"""
read() 括号内可以放数字
在t模式下表示字符个数
在b模式下表示字节个数
英文字符统一使用一个bytes来表示
中文字符统一使用三个bytes来表示
"""
-
小练习
1.简易版本的注册、登陆功能
普通要求(实现一次即可)
注册功能
获取用户名和密码组织成你喜欢的样子写入文件即可
登陆功能
获取用户名和密码然后比对是否与文件内用户数据一致
# 注册功能
# 1.获取用户用户名和密码
username = input('username>>>:').strip()
password = input('password>>>:').strip()
# 2.将用户名和密码组织成一个字符串
data = '%s|%s' % (username, password)
# 3.文件操作 写入数据
with open(r'userinfo.txt', 'w', encoding='utf8') as f:
f.write(data)
print('用户:%s 注册成功' % username)
# 登录功能
# 1.获取用户名和密码(先使用input获取用户输入的数据 然后strip()移除首尾空格 之后赋值给变量名username)
username = input('username>>>:').strip()
password = input('password>>>:').strip()
# 2.获取文件内真实的用户数据
with open(r'userinfo.txt','r',encoding='utf8') as f:
# 由于现在文件中只有一行内容 我们干脆直接读取完
data = f.read() # 'jason|jason123'
'''with子代码执行完之后的结果是可以在外面使用的'''_
# 3.切割字符串获取真实的用户名和密码
res = data.split('|') # ['jason', 'jason123']
'''这里也可以直接使用解压赋值的操作 real_name,real_pwd = data.split('|')'''
# 4.比对数据
if username == res[0] and password == res[1]:
print('登录成功')
else:
print('用户名或密码错误')
-
进阶练习
# 多用户注册
# while True:
# # 1.获取用户用户名和密码
# username = input('username>>>:').strip()
# password = input('password>>>:').strip()
# # 2.将用户名和密码组织成一个字符串
# data = '%s|%s\n' % (username, password)
# # 2.1.判断用户名是否已存在
# with open(r'userinfo.txt', 'r', encoding='utf8') as f1:
# # 2.2.循环读取每一行用户数据
# for line in f1:
# # 2.3.获取每一行数据中的用户名
# real_name, real_pwd = line.split('|')
# # 2.4.判断用户名是否一致
# if username == real_name:
# print('用户名已存在')
# break
# else:
# # 3.文件操作 写入数据
# with open(r'userinfo.txt', 'a', encoding='utf8') as f:
# f.write(data)
# print('用户:%s 注册成功' % username)
# 多用户登录
# 1.获取用户名和密码(先使用input获取用户输入的数据 然后strip()移除首尾空格 之后赋值给变量名username)
username = input('username>>>:').strip()
password = input('password>>>:').strip()
# 2.获取文件内真实的用户数据
with open(r'userinfo.txt', 'r', encoding='utf8') as f:
for line in f:
# 3.切割字符串获取真实的用户名和密码
'''注意密码末尾有\n'''
real_name, real_pwd = line.split('|') # ['jason', 'jason123\n']
# 4.比对用户名和密码是否正确
if username == real_name and password == real_pwd.strip('\n'):
print('登录成功')
break
else:
print('用户名或密码错误')
-
代码整合
while True:
print("""
1.用户注册
2.用户登录
""")
choice = input('请输入您想要执行的功能编号>>>:').strip()
if choice == '1':
# 1.获取用户用户名和密码
username = input('username>>>:').strip()
password = input('password>>>:').strip()
# 2.将用户名和密码组织成一个字符串
data = '%s|%s\n' % (username, password)
# 2.1.判断用户名是否已存在
with open(r'userinfo.txt', 'r', encoding='utf8') as f1:
# 2.2.循环读取每一行用户数据
for line in f1:
# 2.3.获取每一行数据中的用户名
real_name, real_pwd = line.split('|')
# 2.4.判断用户名是否一致
if username == real_name:
print('用户名已存在')
break
else:
# 3.文件操作 写入数据
with open(r'userinfo.txt', 'a', encoding='utf8') as f:
f.write(data)
print('用户:%s 注册成功' % username)
elif choice == '2':
# 1.获取用户名和密码(先使用input获取用户输入的数据 然后strip()移除首尾空格 之后赋值给变量名username)
username = input('username>>>:').strip()
password = input('password>>>:').strip()
# 2.获取文件内真实的用户数据
with open(r'userinfo.txt', 'r', encoding='utf8') as f:
for line in f:
# 3.切割字符串获取真实的用户名和密码
'''注意密码末尾有\n'''
real_name, real_pwd = line.split('|') # ['jason', 'jason123\n']
# 4.比对用户名和密码是否正确
if username == real_name and password == real_pwd.strip('\n'):
print('登录成功')
break
else:
print('用户名或密码错误')
else:
print('没有改功能 爱咋滴咋滴!')