"""文件操作(基础知识)"""
import os
# 当前py文件的上一层目录
path_basic = os.path.abspath("")
# 1.打开和关闭文件
"""
f = open(r"文件地址", mode='rt', encoding='utf-8')
res = f.read()
print(res)
f.close()
del res
"""
"""
若使用 with 实现打开文件的操作,在执行完程序后,将会自动关闭被打开的系统文件
同时,这种方法还能实现同时打开多个文件的操作
"""
# # 2.同时打开两个文件
# with open(fr'{path_basic}\userDate.txt', mode='rt', encoding='utf-8') as f1, \
# open(fr'{path_basic}\b.txt', mode='rt', encoding='utf-8') as f2:
# x1 = f1.read()
# x2 = f2.read()
# print(x1)
# print(x2)
#
# # 3.读取文件数据
# with open(fr'{path_basic}\userDate.txt', mode='rt', encoding='utf-8') as f1:
# address = input('请输入文件路径>>>').strip()
# content = open(fr'{address}', mode='rt', encoding='utf-8')
#
# print('第1次读'.center(80, '-'))
# bobo_1 = content.read()
# print(bobo_1)
#
# print('第2次读'.center(80, '-'))
# bobo_2 = content.read()
# print(bobo_2)
"""
补充:
(1)
r 只read
w 只write
userDate.txt 只能写但不能读(append),追加写,(写是追加在原有文件内容的末尾)
(2)
t是文本类
b是图片视频类
"""
# 4.指针移动:
"""
f.seek(offset, whence)---f 指的是需要操作的文件对象
参数:
offset: 将光标向前移动n个位置
whence: 参考位置,一般参数为0,1,2
0 :将开头作为参考位置
1 :将当前作为参考位置
2 :将末尾作为参考位置
seek(offset, whence)方法用于移动文件读取指针到指定位置
参数说明>>>
offset --- 开始的偏移量,也就是代表需要移动偏移的字节数
whence --- 可选,默认值为 0。
给offset参数一个定义,表示要从哪个位置开始偏移:
0代表从文件开头开始算起,1代表从当前位置开始算起,2代表从文件末尾算起。
"""
with open(fr'{path_basic}\a.txt', mode='rb') as f:
f.seek(0, 0)
print(f.tell()) # tell()方法返回文件的当前位置,即文件指针当前位置
"""修改文件"""
import os
# 当前py文件的上一层目录
path_basic = os.path.abspath("")
"""
方式一(文本编辑器修改文件的方式)
优点:修改方便,修改快捷(吸引用户)
缺点:费内存...
"""
# 打开要修改的文件,导入信息到内存里面
with open(fr'{path_basic}\document_1.txt', mode='rt', encoding='utf-8') as f1:
# 将硬盘里的信息"全部"导入内存,费内存
infomation = f1.read()
# 将内存的信息变成列表
p = list(infomation)
# 向列表里面插入新内容
p.insert(3, '不')
# 将"修改完的列表"的信息转为"非列表格式"
new_infomation = "".join(p)
# 再次打开原文件,此时,由于是w模式,因此,它打开的那一瞬间会清空原文件里面的数据
# 因为我们已将原文件的数据存储到了内存中,而且修改后的数据也储存到了内存中,因此不用担心数据丢失
with open(fr'{path_basic}\document_1.txt', mode='wt', encoding='utf-8') as f1:
# 将内存中的new_infomation信息写入到硬盘里面
f1.write(new_infomation)
"""
方式二
将A文件的数据 + 需要修改的数据---> 放到B文件中,
将A文件删除,同时B文件改名为A文件
"""
# 同时打开两个文件,一个"呼出"数据,同时另一个"吸收"数据,过程中若需要的话,可对数据进行一定的修改
with open(fr'{path_basic}\document_2.txt', mode='rt', encoding='utf-8') as f1:
with open(fr'{path_basic}\document_2(副本).txt', mode='wt', encoding='utf-8') as f2:
# 每次只从硬盘里面读一行,这样占用的内存就少了,但是速度就慢了
for line in f1:
# replace() 方法把字符串中的 old(旧字符串) 替换成 new(新字符串),
# 如果指定第三个参数max,则替换不超过 max 次
new_line = line.replace('一天', '一年')
f2.write(new_line)
# 删旧改新
os.remove(fr'{path_basic}\document_2.txt')
os.rename(fr'{path_basic}\document_2(副本).txt', fr'{path_basic}\document_2.txt')
# t模式下的————Copy功能
# old_path = input('请输入原文件路径>>>').strip()
# new_path = input('请输入新文件路径》>>>').strip()
# with open(fr'{old_path}', mode='rt', encoding='utf-8') as f1,\
# open(fr'{new_path}', mode='wt', encoding='utf-8') as f2:
# res = f1.read()
# f2.write(res)
# b模式下的————Copy功能 (瑕疵版)
# old_path = input('请输入原文件路径>>>').strip()
# new_path = input('请输入新文件路径》>>>').strip()
# with open(fr'{old_path}', mode='rb') as f1,\
# open(fr'{new_path}', mode='wb') as f2:
# for line in f1:
# f2.write(line)
#
# b模式下的————Copy功能 (改良版)
old_path = input('请输入原文件路径>>>').strip()
new_path = input('请输入新文件路径》>>>').strip()
with open(fr'{old_path}', mode='rb') as f1, \
open(fr'{new_path}', mode='wb') as f2:
while 1:
res = f1.read(1024) # 每次读取字节数,这样做可以控制--单次输入量!相对减少运行负荷。
# 补充说明:if 后面的内容只有为ture时,才执行 if 语句!
if not res: # 等价于 len(res) == 0
break
f2.write(res)
import os
"""统计文件的字符数量"""
# 被统计的文件目录
p = os.path.abspath("")
path = p + r"\date.txt"
with open(path, mode='rt', encoding='utf-8') as f:
# sum()里面处理的对象为一个可迭代的对象, 如列表、生成器等。
generator = (len(line) for line in f)
result = sum(generator)
print(result)
"""
补充说明:
以上是统计文件字符数量的最终方案,也是效率最高,最节省计算机资源的方案!
sum()里面的这个整体 ( len(line) for line in f ) 不是元组生成式!因为元组不可变。
它是生成器表达式,它本身没有任何值的,只有next它的时候,它才产生一个值。
生成器其实是自定义的迭代器!
"""
目标:模块化实现注册与登录校验功能,要求数据存入文件中。
具体实现:如下
"""辅助工具"""
# 判断"目标字符串"是否存在于文件中
def exist(string, filePath):
with open(fr"{filePath}", "rt", encoding="utf-8") as f1:
for line in f1:
n, p = line.split(":")
if string == n:
return True
return False
# 判断"用户信息"是否匹配
def matching(name, password, filePath):
with open(fr"{filePath}", "rt", encoding="utf-8") as f1:
for line in f1:
n, p = line.strip("\n").split(":")
if name == n and password == p:
return True
return False
from smallTools import exist
def registration(path):
# >获取用户名和密码
print("注册界面".center(12, "*"))
# >>用户名获取和确认
while True:
name = input("用户名>>>").strip()
if not exist(name, path):
break
print("用户名已存在!")
# >>密码获取和确认
while True:
password_1 = input("设置密码>>>").strip()
password_2 = input("确认密码>>>").strip()
if password_2 == password_1:
break
print("两次密码不一致,请重新设置密码!")
# >拼接用户信息
info = "{}:{}\n".format(name, password_2)
# >存储用户名和密码
with open(path, mode="at", encoding="utf-8") as f1:
f1.write(info)
# >提示
print("注册成功!")
from smallTools import matching
def login(path):
print("登录界面")
# >获取用户信息
name = input("请输入账号>>>").strip()
password = input("请输入密码>>>").strip()
# >信息匹配
if matching(name, password, path):
print("登录成功!")
return None
print("登录失败,账号或密码错误!")
import os
from register import registration
from login import login
# 用户数据文件地址
p = os.path.abspath("")
path = p + r"\userDate.txt"
"""登录系统入口"""
while True:
print()
print("欢迎来到注册登录系统".center(15, "*"))
print("0.退出".center(22, "*"))
print("1.前往注册".center(20, "*"))
print("2.前往登录".center(20, "*"))
s = input("\n请输入功能序号>>>").strip()
if s == "0":
break
if s == "1":
registration(path)
if s == "2":
login(path)
目标:运行"用户充值"程序,然后运行"日志监控"程序查看用户的充值情况
具体实现:如下
"""用户充值"""
import os
import time
# log日志文件目录
p = os.path.abspath("")
path = p + r"\user.log"
while True:
money = input("请输入您想要充值的金额:").strip()
with open(path, mode='at', encoding='utf-8') as f:
f.write(f"%s,小明成功充值了{money}元\n" % time.strftime('%x %X %A'))
"""日志监控"""
import os
import time
# log日志文件目录
p = os.path.abspath("")
path = p + r"\user.log"
with open(path, mode='rb') as f:
# 控制文件指针跳到末尾
f.seek(0, 2)
# 一直循环,取最后一行的信息
while True:
line = f.readline().decode('utf-8')
if line:
print(line, end='')
time.sleep(1)