文件操作

  今日内容

  • 文件的读写模式
  • 文件的操作模式
  • 文件的一些操作方法
  • 文件内光标的移动
  • 文件内数据的修改
  • 作业

文件的读写模式

文件可以读写模式主要分为三种模式分别为 r、w、a

# 1.with语法支持一次性打开多个文件  只要在每个open后几个逗号即可
with open(r'a.txt', 'r', encoding='utf8') as f1, open(r'b.txt', 'r', encoding='utf8') as f2, open() as f3:
    pass

1.r模式

r模式  只读模式  是open默认的模式

  在r模式的转态下打开文件下只能读 不能进行其他相关操作(写)

# 在有文件路径下打开文件 r模式不会报错
with open(r'b.txt', 'r', encoding='utf8') as f:
    print(f.read())
    print(f.write())  # 会报错 因为r模式只能读不能写
# 在没有文件路径下打开文件 r模式会直接报错
with open(r'c.txt', 'r', encoding='utf8') as f:
    print(f.read())
# 如果你只写了文件目录没有写后面的参数open默认你写了r模式
with open(r'b.txt') as f1:
    print(f1.read())

2.w模式

w模式 只写模式

  在w模式转态下打开文件下只能写 不能进行其他相关操作(读)

# 在有文件路径下打开文件 w模式不会报错
info = 'python ON.1'
with open(r'b.txt', 'w', encoding='utf8') as f:
    print(f.write(info))  # 还能够计算文件中有多少个字符
    print(f.read())  # 会报错 因为w模式只能写不能读
# 在没有文件路径下打开文件 w模式不会报错会直接在当前py文件下创建你文件的名字
with open(r'c.txt', 'w', encoding='utf8') as f:
    print(f.write(info))
'''
w写文件时它会先把文件内容里的所有数据清除然后在编写你写进去的程序
所以你不管运行多少次 文件里只有你程序最后运行的结果的数据
'''

3.a模式

a模式 只追加模式

  在a模式下打开文件下默认在末尾追加内容 不能进行其他相关操作(读)

# 在有文件路径下打开文件 w模式不会报错
info = 'python ON.1\n'
with open(r'b.txt', 'a', encoding='utf8') as f:
    print(f.write(info))
    print(f.read())  # 会报错 因为a模式只能写不能读
# 在没有文件路径下打开文件 a模式也不会报错会直接在当前py文件下创建你文件的名字
with open(r'd.txt', 'a', encoding='utf8') as f:
    print(f.write(info))
'''
a模式写入文件时它不会清除文件里的内容 会直接在文件尾部添加数据
'''

4.+模式

+模式 就是可读可写

  可以与上面三种联合用 r+、w+、a+、rb+、wb+、ab+

r+和rb+其实是跟r与rb的特性是一样的 只不过它可以既可以读也可以写

w+和wb+也跟w与wb的特性一样 只不过它也可以写也可以读

a+和ab+也跟a与ab的特性是一样 也是在文件末尾添加新值和读取文件

只不过如果不加b的模式只能操作文本文件 带b是操作二进制模式

with open(r'a.txt', 'a+', encoding='utf8') as f:
    res1 = f.write('tony|123\n')
    print(res1)
    res2 = f.read()
    print(res2)

# +就是能在子代码中能够既读也可以写

文件的操作模式

文件的操作模式主要分为两种 t、b 默认t

1.t模式

t模式其实就是文本模式

  只能够操作文本文件  文件操作的默认模式

t模式下有三种 rt、wt、at

如果是操作文本文件的话是要在t模式下操作的 可以简写为r、w、a

就是上面的三种文件读写模式  因为文件的操作默认的就是t模式所以可以简写

t模式:

1.只能操作文本文件  不能操作其他文件类型(视频文件、图片文件...)

2.必须要指定encoding参数

3.读写都是以字符串形式参与的

2.b模式

b模式其实就是二进制模式

  文件内容都是以二进制进行操作的

b模式下有三种rb、wb、ab 这个不能简写

它能够操作所有类型文件

b模式:

1.能够操作所有类型的文件
2.不需要指定encoding参数
3.读写都是以bytes为单位(二进制数)

with open('111.jpeg', 'rb') as f1, open('222.jpeg', 'wb') as f2:
    f2.write(f1.read())
'''
这个是个图片型文件 必须要用b模式因为t模式只能操作文本文件
这个意思就在先在打开111.jpeg文件然后读取
然后在打开222.jpeg文件 因为是w模式就会直接在当前.py文件下创建
然后在222.jpeg文件下写入从111.jpeg文件读取的内容
'''

文件的一些操作方法

read()  # 可以一次性读取文件内的内容并且光标会停留在文件的末尾 如果继续读就会为空
'''当文件的数据过大时 不推荐使用 因为不管文件的大小read都是一次性读出来 有可能造成内存溢出'''
for line in f:
    print(line)  # for循环也是可以循环文件的可以把文件一行一行的循环出来 不会直接循环全部
write()  # 写入内容
readline() # 一次只读取一行内容
readlines()  # 按照行的方式读取所有内容然后组织成列表返回
readable()  # 判断是否可读
writable()  # 判断是否可写
writelines  # 支持填写容器类型(内部可以存放多个数据值的数据类型)多个数据值
flush()  # 将内存中的文件立刻刷到硬盘中(相当于按了Ctrl+s)
'''这么多方法中只有前三个的方法是最重要的'''

文件内的光标移动

1.read()的一些使用

read是可以在括号内存入参数的 意思是读取文件中几个字符或是字节

比如有个文件a.txt 里面就只写了 abc你好啊

with open(r'a.txt', 'r', encoding='utf8') as f:
    res = f.read(4)
    print(res)  # abc你
# read()括号内是可以填写参数的 在文本模式下的单位是字符为单位 写几个就读出几个字
with open(r'a.txt', 'rb') as f:
    res = f.read(4)
    print(res)   # b'abc\xe4'
    res1 = res.decode()
    # 因为读取二进制数的位数是4但是中文的字节为3个
    # abc个有一个字节所以只有一个字节是读不出来中文的
    # print(res1)  # 报错
    res = f.read(6)
    print(res)  # b'abc\xe4\xbd\xa0'
    res1 = res.decode()
    print(res1)  # abc你
# read()括号内是可以填写参数的 在二进制模式下的单位是bytes为单位 (英文是一个字节 中文是三个字节)

2.tell()关键字

还有一个可以获取光标移动了多少个字节

关键字时 tell()  获取光标移动的字节数

with open(r'a.txt', 'r',encoding='utf8')as f:
    res = f.read(4)
    print(res)  # abc你
    print(f.tell())  # 字节为单位  英文为一个字节中文为三个字节 所以为6
with open(r'a.txt', 'rb')as f:
    res = f.read(4)
    print(res)  # b'abc\xe4'
    print(f.tell())  # 4 因为获取光标的单位本来就是二进制数 所以你输入啥就返回啥

3.seek()关键字

seek()可以控制光标的移动

# 关键字 seek()
#     seek(offset,whence)
'''
offset : 控制光标移动的位移量(字节数)
whence : 控制光标移动的模式
whence 有三种模式 0,1,2
0  基于文件的开头移动多少字节
1  基于光标当前所在的位置移动所少字节
2  基于文件的末尾移动多少字节
1和2只能在二进制模式使用  0在t和b中都可以使用
'''
with open(r'a.txt', 'r', encoding='utf8') as f:
    res = f.read(4)
    print(res)  # abc你
    # 现在光标在你这个字的后面 而如果还想读全部的话可以用关键字seek()
    f.seek(0, 0)
    print(f.read())  # abc你好啊
    f.seek(6, 0)
    # 第一个数字就是控制光标往后几个字节开始读取内容
    # 第二数字为模式0所以从文件的开头开始
    # 是按字节来算的(英文一个字节 中文三个字节)
    print(f.read())  # 好啊
    # f.seek(2,1)  # 报错
    print(f.read())
with open(r'a.txt', 'rb') as f:
    res = f.read(3)
    print(res)  # b'abc'
    res1 = res.decode()
    print(res1)  # abc
    # 现在光标在c字母后面
    # f.seek(3, 1)
    # 1模式就是在光标当前位置开始移动
    # 3的意思让光标往右移动3个字节在打印
    # 因为3个字节刚好是一个中文刚好跳过你这个中文
    # print(f.read().decode('utf8'))  # 好啊
    f.seek(-3, 1)
    # 控制看光标移动的还可以写负数控制方向
    # -3的意思是让光标往左边移动3个字节在读取内容
    print(f.read().decode('utf8'))  # abc你好啊
    f.seek(-3, 2)
    # 2模式是让光标跳到末尾开始移动光标
    # -3的意思让光标往走移动三个字节然后在读取内容
    print(f.read().decode('utf8'))  #

文件内修改数据的操作

机械硬盘存储数据的原理:

  数据的修改其实就是在机械硬盘上原来的存储的去掉在原来的地方刻上修改后的内容

  数据的删除其实就是在机械硬盘上把占有态把它改为自由态 自由态就可以重新存储数据

代码修改文件的方式
  1.覆盖写
    先读取文件内容到内存 在内存中完成修改 之后w模式打开该文件写入
  2.重命名
    先读取文件内容到内存 在内存中完成修改 之后保存到另外一个文件中
  再将原文件删除 将新的文件重命名为原文件

# 覆盖写
with open(r'a.txt', 'r', encoding='utf8')as f:
    data = f.read()  # 把内容提取出来
new_data = data.replace('abc','cbd')  # 利用replace方法把想要换掉的字符给替换掉
with open(r'a.txt','w',encoding='utf8')as f:
    f.write(new_data)  # 在重新写入进去
'''
优点:硬盘只占用一块空间
缺点:数据量较大的时候会造成内存溢出
'''

# 重命名
import os

with open('demo.txt', 'r', encoding='utf8') as read_f, \
        open('.demo.txt.swap', 'w', encoding='utf8') as wrife_f:
    for line in read_f:
        wrife_f.write(line.replace('cbd', 'abc'))
os.remove('demo.txt')  # 删除文件
os.rename('.demo.txt.swap', 'demo.txt')  # 重命名文件
'''
优点:不会造成内存溢出
缺点:有那么一段时间需要占用硬盘两个地方的空间(可能)   也可能是在内存中创建没有刷到硬盘
''' 

作业

1.编写简易版本的拷贝工具

要求:

自己输入想要拷贝的数据路径
自己输入拷贝到哪个地方的目标路径
任何类型数据皆可拷贝
ps: 个别电脑C盘文件由于权限问题可能无法拷贝
换其他盘尝试即可
cope_path = input(r'请输入你要拷贝的路径>>>:').strip()
output_path = input(r'请输入你要输出的路径>>>:').strip()
with open(cope_path, 'rb') as f1, open(output_path, 'wb') as f2:
    f2.write(f1.read())

2.利用文件充当数据库编写用户登录、注册功能

用户注册功能 >> >: 文件内添加用户数据(用户名、密码等)
用户登录功能 >> >: 读取文件内用户数据做校验
ps: 上述功能只需要实现一次就算过关(单用户)
文件内始终就一个用户信息
单用户
# 1.获取用户名和密码
username = input('请输入你的用户名>>>:').strip()
password = input('请输入你的密码>>>:').strip()
# 2.按照w模式打开文件
with open(r'userinfo.txt', 'w', encoding='utf8') as f1:
    # 3.将用户名和密码按照  xxx|123 存入
    f1.write(f'{username}|{password}')
# 4.获取用户名和密码
username1 = input('please input your name>>>:').strip()
pwd = input('please input your password>>>:').strip()
# 5.按照r模式打开文件
with open(r'userinfo.txt', 'r', encoding='utf8') as f2:
    # 6.读取f2按照'|'分割解压赋值
    real_name, real_pwd = f2.read().split('|')
    # 7.判断
    if username1 == real_name:
        if pwd == real_pwd:
            print('登入成功')
        else:
            print('密码错误')
    else:
        print('用户名错误')
用户可以连续注册
用户可以多账号切换登录(多用户)
文件内有多个用户信息
ps: 思考多用户数据情况下如何组织文件内数据结构较为简单
提示: 本质其实就是昨天作业的第二道题
只不过数据库由数据类型变成文件

多用户

# 1.循环打印功能
while True:
    print("""
    1.注册
    2.登入
    3.查看用户
    """)
    # 2.输入功能
    choice = input('请选择编号>>>:').strip()
    # 3.判断功能呢分割
    if choice == '1':
        # 4.获取用户名和密码
        username = input('请输入你的用户名>>>:').strip()
        password = input('请输入你的密码>>>:').strip()
        # 5.r模式打开文件 判断用户名是否存在
        with open(r'a.txt', 'r', encoding='utf8') as f1:
            for line in f1:
                if username in line:
                    print('用户名已存在')
                    break
            else:
                # 6.将用户名和密码按照 xxx|123 存入 
                data_info = f'{username}|{password}\n'
                # 7.a模式打开 存入内容
                with open(r'a.txt', 'a', encoding='utf8') as f2:
                    f2.write(data_info)
                    print('注册成功')
    elif choice == '2':
        # 8.获取用户名和密码
        username = input('please input your name>>>:').strip()
        pwd = input('please input your password>>>:').strip()
        # 9.r模式打开
        with open(r'a.txt', 'r', encoding='utf8') as f3:
            for line in f3:
                # 10.解压赋值
                real_name, real_pwd = line.split('|')
                # 11.判断用户名和密码
                if real_name == username and real_pwd.strip('\n') == pwd:
                    print('登入成功')
                    break
            else:
                print('用户名或密码错误')
    elif choice == '3':
        # 12.r模式打开
        with open(r'a.txt', 'r', encoding='utf8')as f4:
            for line in f4:
                # 按照|分割提取0索引
                real_name = line.split('|')[0]
                print(real_name)
    else:
        print('请输入正确的数字')

3.利用函数编写文件充当数据库编写用户登录、注册功能

def register():  
    username = input('请输入你的用户名>>>:').strip()
    password = input('请输入你的密码>>>:').strip()
    # 5.r模式打开文件 判断用户名是否存在
    with open(r'a.txt', 'r', encoding='utf8') as f1:
        for line in f1:
            if username in line:
                print('用户名已存在')
                return
        else:
            # 6.将用户名和密码按照 xxx|123 存入
            data_info = f'{username}|{password}\n'
            # 7.a模式打开 存入内容
            with open(r'a.txt', 'a', encoding='utf8') as f2:
                f2.write(data_info)
                print('注册成功')


def login():
    username = input('please input your name>>>:').strip()
    pwd = input('please input your password>>>:').strip()
    # 9.r模式打开
    with open(r'a.txt', 'r', encoding='utf8') as f3:
        for line in f3:
            # 10.解压赋值
            real_name, real_pwd = line.split('|')
            # 11.判断用户名和密码
            if real_name == username and real_pwd.strip('\n') == pwd:
                print('登入成功')
                return
        else:
            print('用户名或密码错误')


while True:
    print("""
    0 :退出
    1 :注册
    2 :登入 
    """)
    choice = input('请输入功能编号>>>:').strip()
    if not choice.isdigit():
        print('请输入数字或内容')
        continue
    if choice == '0':
        print('欢迎下次光临')
        break
    elif choice == '1':
        register()  # 调用自己编写的注册函数
    elif choice == '2':
        login()  # 调用自己编写的登入函数
    else:
        print('请输入正确的功能编号')

 

 

 

 

 

posted @ 2022-06-29 16:12  stephen_hao  阅读(139)  评论(0)    收藏  举报