十一、 文件处理

一 文件操作简介

应用程序在运行过程中产生的数据都是先存放在内存中,如果想要永久保存数据,就必须存到硬盘里,应用程序想要操作硬件,就必须通过操作系统,文件就是操作系统提供给用户操作硬盘的快捷方式之一。

二 文件操作流程

2.1 open() as f:

#  创建一个文件a.txt
#  关键字open
#  参数(file, mode='r', buffering=None, encoding=None,
#       errors=None, newline=None, closefd=True)
f = open(r'a.txt', mode='r', encoding='utf8')
#  第一个参数文件路径,第二个参数模式,第三个参数编码格式
print(f.read())  # 今天学习的内容是文件的基本操作
f.close()  # 回收系统资源

这种方式在操作完文件后需要添加f.colse()方法回收资源,我们可能会忘记,所以python提供了第二种写法。

2.2 with open() as f:

# 关键字with open() af 变量名:
with open(r'a.txt', mode='r', encoding='utf8') as f:
    res = f.read()
    print(res)  # 今天学习的内容是文件的基本操作
# 这种方法在执行完with子代码后会自动执行close方法

# with语法补充
# 打开多个文件 中间用空格隔开
with open(r'userinfo.txt', mode='r', encoding='utf8') as f, open(r'xxx.txt', mode='r', encoding='utf8') as f1:

2.3 文件路径格式

在文件路径下面加r是为了统一格式

with open('D:\python\n\r', mode='r', encoding='utf8') as f:
# 如果不加r,python解释器会将\n\r识别成换行而不是一个路径

三 文件读写模式

3.1 r模式

只读模式,如果不写mode参数,默认为只读模式,以该模式打开文件,只能查看内容,不能进行其他操作。

# r模式

# 如果文件地址不正确则报错
# FileNotFoundError: [Errno 2] No such file or directory: 'test'
# 文件未找到:没有这样的文件或目录
with open(r'test', mode='r', encoding='utf8') as f:
    res = f.read()
    print(res)

# 文件路径存在 r模式会打开文件等待读取指令
with open(r'userinfo.txt', mode='r', encoding='utf8') as f:
    res = f.read()
    print(res)  # jasper:123
    f.write('jack:123')  # 报错 io.UnsupportedOperation: not writable
    # 不具备写的功能

3.2 w模式

只写模式,再能写内容不能进行其他操作,文件不存在时会创建新文档,文件存在时会清空文档,指针移到开头位置。

# w模式
with open(r'userinfo.txt', mode='w', encoding='utf8') as f:
    # res = f.read()
    # print(res)  # 报错 io.UnsupportedOperation: not readable
    # # 不具备读的能力
    f.write('jack:123|')
    f.write('jasper:123|')
    f.write('lili:123|')  # jack:123|jasper:123|lili:123|
    # 文件在w模式下 连续的写入 后面的一定跟在前面的
    # 重新以w模式打开文件 文件会被清空

3.3 a模式

只追加模式,只能追加内容不能进行其他操作,打开文件名不存在就新建一个文件,打开文件名存在,不会清空文件内容,并在文件末尾位置添加新内容。

# a模式
with open(r'userinfo.txt', mode='a', encoding='utf8') as f:
    # res = f.read()
    # print(res)  # 报错 not readable
    f.write('jack:123|')  # 文件内:jack:123|jasper:123|lili:123|jack:123|
    # a模式不会清空文件原本内容 并在文件尾部进行追加

3.4 x模式

创建一个新文件可写

# x模式
# 创建一个新的文件并打开写

with open(r'userinfo.txt', mode='x', encoding='utf8') as f:
    pass
#  文件名存在则报错 [Errno 17] File exists: 'userinfo.txt'

# 文件名不存在则创建一个新的文件
with open(r'c.txt', mode='x', encoding='utf8') as f1:
    print(f1.read())  # 不能读 报错 not readable

with open(r'd.txt', mode='x', encoding='utf8') as f2:
    f2.writelines(['sss', 'eeee'])  # 可以写
    
with open(r'e.txt', mode='xb') as f2:
f2.writelines(['sss'.encode('utf8'), 'eeee'.encode('utf8')])  # 支持二进制模式

3.5 +模式

打开一个磁盘文件,可读可写(r+ w+ a+)

# +模式
# 打开一个磁盘文件更新 可以读也可以写
with open(r'xxx.txt', mode='r+', encoding='utf8') as f:
    pass  # 文件名不存在报错 No such file or directory: 'xxx.txt' 没有这样的文件

with open(r'e.txt', mode='r+', encoding='utf8') as f1:
    print(f1.read())  # ssseeee 可读
    f1.write('xxx')
    print(f1.read())  # ssseeeexxx 可写

with open(r'e.txt', mode='rb+') as f2:
    print(f2.read())  # b'ssseeeexxxxxxxxxxxx'
    f2.write('xixi'.encode('utf7'))  # 支持二进制模式 

四 文件操作模式

4.1 t模式

文本模式,文件操作默认模式,只能操作文本文件,必须给encoding传参,读写都是以字符串为单位。

4.2 b模式

二进制模式,可以操作任意类型文件,读写都是以bytes为单位,必须指定mode参数(rb/wb/ab),encoding参数为空或者不写。

# b
with open(r'userinfo.txt', mode='rb', encoding=None) as f:
    res = f.read()
    print(res)  # b'\xe6\x96\x87\xe4\xbb\xb6'

五 文件操作方法

with open('userinfo.txt', mode='r', encoding='utf8') as f:
    res1 = f.read()  # 读取文件全部内容 继续读则为空
    for line in f:
        print(line)  # 支持for循环 一次读一行
    print(res1)
    res2 = f.readline()  # 读一行
    print(res2)
    res3 = f.readlines()  # 读所有 返回列表里面是字符串
    print(res3, type(res3))
    res4 = f.readable()  # 判断文件是否可读 返回布尔值
    print(res4)
    res5 = f.write('111')  # 报错 不具备写的能力
    print(res5)
    res6 = f.flush()  # 刷新
    print(res6)


with open('userinfo.txt', mode='a', encoding='utf8') as f:
    f.write()  # 写单行
    f.writelines(['666', 'aaa'])  # 写多行 参数是列表里是字符串
    f.writable()

作业

1.编写简易版本的拷贝工具
自己输入想要拷贝的数据路径 自己输入拷贝到哪个地方的目标路径任何类型数据皆可拷贝
ps:个别电脑C盘文件由于权限问题可能无法拷贝 换其他盘尝试即可

path = input('input copy path>>>:')
new_path = input('input copy to path>>>:')
with open(path, mode='rb') as read, open(new_path, mode='ab') as write:
    write.write(read.read())

2.利用文件充当数据库编写用户登录、注册功能
文件名称:userinfo.txt
基础要求:
用户注册功能>>>:文件内添加用户数据(用户名、密码等)
用户登录功能>>>:读取文件内用户数据做校验
ps:上述功能只需要实现一次就算过关(单用户) 文件内始终就一个用户信息
拔高要求:
用户可以连续注册
用户可以多账号切换登录(多用户) 文件内有多个用户信息
ps:思考多用户数据情况下如何组织文件内数据结构较为简单
提示:本质其实就是昨天作业的第二道题 只不过数据库由数据类型变成文件

while True:
    print("""
    1.register function
    2.loging function
    """)
    func = input('Enter function number as>>>:').strip(' ')
    if func == '1':
        # 获取用户注册用户名
        usn = input('Enter username>>>:').strip(' ')
        if usn == '':  # 判断用户是否输入空
            print('No input none')
            continue
        # 判断用户是否存在
        with open(r'userinfo.txt', mode='r', encoding='utf8') as read:
            for i in read:
                # 先写存数据的格式 在完再写校验功能
                # for循环拿到的是一个(usn:pwd换行符)的字符串
                # 先去除字符串的换行符 在以冒号切片 得到用户名和密码列表
                name, password = i.strip('\n').split(':')  # ['jasper', '123']
                if usn == name:
                    print('username already exists')
                    break
            else:
                # 获取用户密码
                pwd = input('Enter password>>>:')
                # 保存用户信息到文本文件
                with open(r'userinfo.txt', mode='a', encoding='utf8') as write:
                    write.write(f'{usn}:{pwd}\n')  # 存储格式为  usn:pwd换行
                    print('register successful')
    elif func == '2':
        # 获取用户账号和密码
        usn = input('Enter username>>>:')
        pwd = input('Enter password>>>:')
        # 校验用户名和密码
        with open(r'userinfo.txt', mode='r', encoding='utf8') as read:
            for i in read:
                # 根据存储数据的格式对数据处理 先去除字符串后的换行符 对列表进行解压赋值
                username, password = i.strip('\n').split(':')  # ['jasper', '123']
                if usn == username and pwd == password:
                    print('loging successful')
                    break
            else:
                print('username or password error')

    else:
        print('Please enter correct function number as')

六 文件内光标移动

6.1 read()参数

# 光标移动
with open(r'userinfo.txt', 'r', encoding='utf8') as f:
    res = f.read(3)  # 在文本模式中 read内参数表示读取字符数
    print(res)


with open(r'userinfo.txt', 'rb') as f1:
    res = f1.read(3)
    print(res)  # b'jas' 在二进制模式下 read内参数指的是读取的bytes数
    print(f1.tell())  # 3 获取文件内光标的位置

6.2 seek()参数

seek方法的offset参数为光标位移量(移动量为字节单位),wence参数是模式,wence有三种模式(0,1,2)

  • 0
    基于文件开头位置进行位移
  • 1
    基于文件光标当前位置进行位移
  • 2
    基于文件末尾位置进行位移

ps:1和2模式只能在二进制模式打开的文件下使用

# seek()
# 参数:offset:控制光标移动的位移量, whence:模式
with open(r'userinfo.txt', 'r', encoding='utf8') as f:
    print(f.tell())  # 0
    f.seek(10, 0)
    print(f.tell())  # 10


with open(r'userinfo.txt', 'rb') as f1:
    print(f1.tell())  # 0
    f1.seek(10, 0)
    print(f1.tell())  # 10
    f1.seek(-1, 1)
    print(f1.tell())  # 9
    f1.seek(-1, 2)
    print(f1.tell())  # 31

小练习
动态查询输入内容

# 动态查询日志
import time

with open(r'userinfo.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('utf8'))
# 文件写入内容
while True:
    with open(r'userinfo.txt', 'ab') as f1:
        f = input('>>>:')
        new = f.encode('utf8')
        f1.write(new)     

七 文件数据修改

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

修改数据:数据覆盖
保存数据:占有态和自由态

7.2 代码修改文件

方式一:覆盖写,将文件先读到内存,在内存内完成修改,在以w模式打开该文件并写入。

with open(r'userinfo.txt', 'rb') as f:
    old = f.read().decode('utf8').replace('s', 'b')
with open(r'userinfo.txt', 'wb') as f:
    new = old.encode('utf8')
    f.write(new)
# 优点:硬盘只占用一块空间
# 缺点:数据内容太大会造成内存溢出

方式二:重命名,将文件读到内存,在内存中完成修改,之后保存到另一个文件夹中,再将原文件删除,再将修改后的文件重命名。

# 重命名
with open(r'userinfo.txt', 'rb') as f, open(r'a.txt', 'ab') as f1:
    for line in f:
        f1.write(line.decode('utf8').replace('b', 's').encode('utf8'))
import os

os.remove('userinfo.txt')
os.rename('a.txt', 'userinfo.txt')
# 优点:不会有内存溢出的问题
# 缺点:额外申请了空间
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值