basicPython-4

文件操作基础知识

"""文件操作(基础知识)"""
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它的时候,它才产生一个值。
生成器其实是自定义的迭代器!
"""

案例演示(一)

目标:模块化实现注册与登录校验功能,要求数据存入文件中。

具体实现:如下

文件名: smallTools.py

"""辅助工具"""


# 判断"目标字符串"是否存在于文件中
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

文件名: register.py

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("注册成功!")

文件名: login.py

from smallTools import matching


def login(path):
    print("登录界面")

    # >获取用户信息
    name = input("请输入账号>>>").strip()
    password = input("请输入密码>>>").strip()

    # >信息匹配
    if matching(name, password, path):
        print("登录成功!")
        return None
    print("登录失败,账号或密码错误!")

文件名: run.py

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)

案例演示(二)

目标:运行"用户充值"程序,然后运行"日志监控"程序查看用户的充值情况

具体实现:如下

文件名: userRecharge.py

"""用户充值"""

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'))

文件名: monitor.py

"""日志监控"""

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)

你可能感兴趣的:(Python基础,python)