【2022-06-30】Python文件处理(二)
Python文件处理
文件模式补充说明
- 针对open() 函数支持的文件打开模式,做出如下补充:
| 模式 | 描述说明 |
|---|---|
| t | 文本模式(默认) |
| x | 写模式,新建一个文件,如果该文件已存在,则会报错 |
| b | 二进制模式 |
| + | 打开一个文件进行更新(可读可写) |
| U | 通用换行模式(不推荐使用) |
| r | 以只读的方式打开文件,文件的指针会放在文件的开头,这是默认模式 |
| rb | 以二级制格式打开一个文件用于只读, 文件指针将会放在文件的开头。这是默认模式。一般用于非文本文件如图片等 |
| r+ | 打开一个文件用于读写。文件指针将会放在文件的开头 |
| rb+ | 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。一般用于非文本文件如图片等 |
| w | 打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 |
| wb | 以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如图片等。 |
| w+ | 打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 |
| wb+ | 以二进制格式打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如图片等。 |
| a | 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
| ab | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
| a+ | 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。 |
| ab+ | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。 |
下图很好的总结了这几种模式:

支持原创,以上内容摘自:https://www.runoob.com/python/python-files-io.html
文件内光标的移动
"""只有在文本模式使用的情况下,read控制的是字符,其余情况都是以字节为单位
userinfo.txt = libai say 人生得意须尽欢,莫使金樽空对月
with open(r'userinfo.txt', 'r', encoding='utf8') as f:
data = f.read(30) # 在文本模式下,read括号内的数字表示读取几个字符
print(data) # libai say 人生得意须尽欢,莫使金樽空对月
with open(r'userinfo.txt', 'rb') as f:
data = f.read(30) # 在二进制模式下,read括号内的数字表示读取几个字节(英文表示一个bytes,中文表示三个bytes)
print(data) # b'libai say \xe4\xba\xba\xe7\x94\x9f\xe5\xbe\x97\xe6\x84\x8f\xe9\xa1\xbb\xe5\xb0\xbd\xe6\xac'
查看目前光标移动的位移量:
print(f.tell()) # 获取光标移动的字节数
如何使用代码控制光标的移动
seek(offset,whence)
offset 控制光标移动的位移量(以字节为单位)
whence 移动的模式
0 基于文件开头的位置往后移动多少字节
1 基于光标当前所在的位置移动多少字节
2 基于文件末尾移动多少字节
1和2只能在二进制模式下使用
# with open(r'userinfo.txt', 'rb') as f:
# data = f.read(4)
# print(data.decode('utf8')) # liba
# # f.seek(-2, 1)
# # print(data.decode('utf8')) # liba
# f.seek(-2, 2)
# print(data.decode('utf8')) # liba
# 小练习:实现动态查看最新一条日志的效果
import time
with open('access.log', '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='')
文件内数据的修改
机械硬盘存储数据的原理
1.数据的修改 其实是覆盖写
2.数据的删除 占有态自由态
# 文件桃园三结义.txt内容如下
刘备 东汉 100 30 10086
关羽 东汉 95 100 10086
张飞 东汉 70 95 10086
# 执行操作
with open('桃园三结义.txt',mode='r+t',encoding='utf-8') as f:
f.seek(9)
f.write('<周瑜打黄盖>')
# 文件修改后的内容如下
刘备<周瑜打黄盖> 100 30 10086
关羽 东汉 95 100 10086
张飞 东汉 70 95 10086
PS:
# 1、硬盘空间是无法修改的,硬盘中数据的更新都是用新内容覆盖旧内容
# 2、内存中的数据是可以修改的
代码修改文件的方式
1.覆盖写
先读取文件内容到内存 在内存中完成修改 之后w模式打开该文件写入
2.重命名
先读取文件内容到内存 在内存中完成修改 之后保存到另外一个文件中
再将原文件删除 将新的文件重命名为原文件
文件修改方式一:覆盖写
# 将文件内容发一次性全部读入内存,然后在内存中修改完毕后再覆盖写回原文件
# 优点: 在文件修改过程中同一份数据只有一份
# 缺点: 会过多地占用内存,当数据量过大时,容易造成内存溢出
with open('123.txt',mode='rt',encoding='utf-8') as f:
data=f.read()
with open('123.txt',mode='wt',encoding='utf-8') as f:
f.write(data.replace('张三','NB'))
文件修改方式二:重命名
# 以读的方式打开原文件,以写的方式打开一个临时文件,一行行读取原文件内容,修改完后写入临时文件...,删掉原文件,将临时文件重命名原文件名
# 优点: 不会占用过多的内存空间
# 缺点: 在文件修改过程中同一份数据存了两份
import os
with open('123.txt',mode='rt',encoding='utf-8') as read_f,\
open('.123.txt.swap',mode='wt',encoding='utf-8') as wrife_f:
for line in read_f:
wrife_f.write(line.replace('NB','张三'))
os.remove('123.txt') # 删除文件
os.rename('.123.txt.swap','123.txt') # 重命名文件
课题演练
1.编写用户注册、登录功能并封装为函数
def user_register():
print("""
1.注册功能
2.登录功能
3.退出程序
""")
func_id = input('请输入功能编号>>>:').strip()
if func_id == '1':
# 1.获取用户名
username = input('请输入用户名>>>:').strip()
# 2.判断当前用户名是否已存在
# 2.1.读取数据文件
with open(r'userinfo.txt', 'r', encoding='utf8') as f:
# 2.2.循环获取文件内容(一个个用户数据)
for line in f: # jason|123 kevin|321 tony|222
# 2.3.拆分出真实用户名 比对
real_name = line.split('|')[0]
# 2.4.判断用户名书否已存在
if username == real_name:
print('用户名已存在')
break
else:
# 一定要理解循环与break continue else的组合使用
password = input('请输入密码>>>:')
# 3.构造用户数据
user_data = '%s|%s\n' % (username, password)
# 4.打开并写入文件
with open(r'userinfo.txt', 'a', encoding='utf8') as f:
f.write(user_data)
# 5.温馨提示
print(f'用户{username}注册成功')
def user_login():
print("""
1.注册功能
2.登录功能
3.退出程序
""")
func_id = input('请输入功能编号>>>:').strip()
if func_id == '2':
# 1.获取用户数据
username = input('username>>>:').strip()
password = input('password>>>:').strip()
# 2.读取文件内容
with open(r'userinfo.txt', 'r', encoding='utf8') as f:
# 2.1.循环读取每个真实用户的数据
for line in f: # oscar|666 jerry|789
# 2.2.拆分真实用户名和密码
real_name, real_pwd = line.split('|') # 注意密码后面有换行符
# 2.3.判断用户输入的数据与真实数据是否一致
if username == real_name and password == real_pwd.rstrip('\n'):
print('登录成功')
break
else:
print('用户名或密码错误')
def user_exit():
print("""
1.注册功能
2.登录功能
3.退出程序
""")
func_id = input('请输入功能编号>>>:').strip()
if func_id == '3':
print('欢迎下次再来哦')
else:
print('输入不合法!!!')
user_register()
user_login()
user_exit()

浙公网安备 33010602011771号