python全栈开发day08文件处理2

基本概念

  • 打开文件的模式有三种纯净模式:r(默认的)、 w 、a
  • 控制操作文件内容格式的两种模式:t(默认的)、b

大前提:tb模式均不能单独使用,必须与纯净模式结合使用

t文本模式

    • 1.读写文件都是以字符串为单位的
    • 2.只能针对文本文件
    • 3.必须指定encoding参数

b二进制模式

    • 1.读写文件都是以bytes/二进制位单位的
    • 2.可以针对所有文件
    • 3.一定不能指定encoding参数

二.打开文件模式详解

  • 1.只读模式(rt):在文件不存在时则报错,文件存在文件内指针直接跳到文件开头
with open(r'a.txt',mode = 'rt',encoding = 'utf-8') as f:          #r的意思是之后跟的是一个纯路径
    print(f.readlines())
    • 用户认证功能
user_name = input('请输入你的用户名:').strip()
user_psw = input('请输入你的密码:').strip()
with open(r'db.txt',mode = 'rt',encoding = 'utf-8') as f:
    for line in f:
        x,y = line.strip('\n').split(':')
        if user_name == x and user_psw == y:
            print('登录成功')
            break
    else:
        print('用户名或密码错误')
       
  • w只写模式(wt):在文件不存在时会创建空文档,文件存在会清空文件,指针跑到文件开头
with open(r'b.txt',mode = 'wt',endocing = 'utf-8') as f:
    print(f.writable())      #判断 可写
    print(f.readable())      #判断 不可读
    f.write('雷猴\n')
    f.write('我猴\n')     #强调:在文件不关闭的情况下,写入是从指针当前位置往下写,如果文件关闭从新打开,之前写入的会被清空
    
    f.write('大噶猴\n')
    f.write('111\n222\n333\n')  #连续写入可以直接连着写,注意换行符\n,换行也是字符一定记得写
'''
我们来定义一个变量列表
用for循环把它的每个量取出在写入文件中
'''
    lines = ['111','222','333']
    for line in lines:        #for循环的写法
        f.write(lines)
    f.writelines(lines)     #writelines方法同样的效果

    • 注册功能:
user_name = input('请设置你的用户名>>:')
user_psw = input('请设置你的密码>>:')
with open(r'b.txt',mode = 'wt',encoding = 'utf-8') as f:
    info = '%s:%s\n' %(user_name,user_psw)
    f.write(info)
    
这里会有一个问题:每一次注册,w只读模式的定义,每次打开文件存在会清空文件,每次注册上一个人注册的数据就不见了
  • a之追加写模式(at):在文件不存在是会创建空文档,文件存在时,文件指针会直接移动到文件最后
with open(r'c.txt',mode = 'at',encoding = 'utf-8') as f:
    print(f.resdable())     #不可读,会报错
    print(f.writable())      #可写
    f.write('1111\n')
with open(r'c.txt',mode = 'at',encoding = 'utf-8') as f:
    f.write('2222\n')        #不管关不关文件,之前的数据都不会被清空,可以用这个实现注册
    
    • 注册功能:
user_name = input('请设置你的用户名>>:')
user_pwd = input('请设置你的密码>>:')
with open('c.txt',mode = 'at', encoding = 'utf-8') as f:
    info = '%s:%s\n' %(user_name,user_pwd)
    f.write(info)

  • b:读写都是以二进制为单位
    • rb:
with open('b.txt',mode='rb') as f:
    data=f.read()
    print(data,type(data))    #输出二进制,类型bytes
    print(data.decode('utf-8'))  #解码成字符,相当于变成rt
with open('d.txt','wb') as f:
    f.write('你好'.encode('utf-8')) #写入以utf-8编码成二进制
    '''
    以b的文件打开方式也能完成对文件的只读、只写、只增加写,
    只是他没有t的文件打开方式那么方便
    '''
with open('1.png',mode='rb') as f:
    data=f.read()
with open('2.png',mode='wb') as f:
    data=f.write(data)
'''
b模式可以对任意文件进行读写,图片、视频都可以
我们可以发现上面的代码的读写,是实现了1.png文件的复制、粘贴
但是如果直接全读,文件过大,内存就爆了,所以我们有要一行一行读,用for循环
'''
#拷贝工具
src_file=input('源文件路径: ').strip()
dst_file=input('目标文件路径: ').strip()
with open(r'%s' %src_file,mode='rb') as read_f,open(r'%s' %dst_file,mode='wb') as write_f:
    for line in read_f:
        # print(line)
        write_f.write(line)
        

文件内指针的移动

大前提:文件内指针的移动是以Bytes为单位的,唯独t模式下的read读取内容个数是以字符为单位的

f.read(3)
with open('a.txt',mode='rt',encoding='utf-8') as f:
    data=f.read(3)       #这个读个数是以字符为单位的
    print(data)

with open('a.txt',mode='rb') as f:
    data=f.read(3)        #这个读个数是以字节Bytes为单位的
    print(data.decode('utf-8'))
  • f.seek(指针移动的字节数,模式控制):控制指针的移动

    • 0(默认模式):该模式代表指针移动的字节数是以文件开头做参照物的
    • 1:该模式代表指针移动的字节数是以当前位置做参照物的
    • 2:该模式代表指针移动的字节数是以文件末尾做参照物的

    强调:其中0模式可以在t模式和b模式使用,而1跟2模式只能在b模式下使用

      f.tell()查看文件指针当前距离文件开头的位置
    

0模式详解:

with open(r'c.txt',mode = 'rt',encoding = 'utf-8') as f:
    f.seek(4,0)
    print(f.tell)
    print(f.read())

with open(r'c.txt',mode = 'rb') as f:
    #f.seek(4,0)
    f.seek(2,0)     #指针移动2bytes不到一个中文字符
    print(f.tell())
    print(f.read().decode('utf-8'))    #报错

1模式

with open('a.txt',mode='rb') as f:
    f.seek(3,1)
    print(f.tell())    #计算时从开头开始计算的
    f.seek(4,1)
    print(f.tell())     #返货7
    print(f.read().decode('utf-8'))

2模式

with open('a.txt',mode='rb') as f:
    f.seek(-9,2)      #指针在末尾,只能往回带移动指针
    data=f.read()
    print(data.decode('utf-8'))
  • 根据2模式可以写一个日记的读写功能

先来分析,首先写日记,日记要存起来,如果我们只是想看当天的日记用2模式,2模式指针跳到最后,现在指针后面是没有内容的,就都不到东西。当文件被输入一个新内容后,指针后面就有内容,就可以独处内容,指针又会到最后,每次读出来的都是新输入进去的内容

# tail -f access.log
with open('access.log',mode='rb') as f:
    f.seek(0,2)
    while True:
        line=f.readline()
        if len(line) == 0:
            # 没有内容
            continue
        else:
            print(line.decode('utf-8'),end='')  
#写一个输入内容的功能
import time       #这个方法可以拿到实时时间用time.strftime('%Y-%m-%d %X')

with open('access.log',mode='at',encoding='utf-8') as f:
    f.write('%s 下雨了alex快跑\n' %time.strftime('%Y-%m-%d %X'))

文件修改

  • 须知一:

硬盘空间无法修改,硬盘中的数据更新都是用新的内容覆盖旧的内容 内存控制可以修改

    with open('a.txt',mode = 'r+t',encoding = 'utf-8') as f:
        f.seek(4,0)
        print(f.tell())
        f.write('是添加还是覆盖')
  • 须知二:

文件对应的是硬盘空间,硬盘不能修改所以文件本质也不能修改,
我们看到文件的内容可以修改,是如何实现的呢?
*大的思路:*将硬盘中的文件读入内存中,在内存中修改完之后再覆盖回硬盘

    • 具体实现分两种:
      • 1.将硬盘中的文件内容一次性读入硬盘,然后在内存中修改完毕后 再覆盖到回硬盘中的原文件
        • 优点:在文件修改过程中同一份数据只有一份,不会过多占用硬盘空间
        • 缺点:会过多的占用内存
with open('db.txt',mode='rt',encoding='utf-8') as f:
    data=f.read()

with open('db.txt',mode='wt',encoding='utf-8') as f:
    f.write(data.replace('kevin','SB'))

      • 2.以读的方式打开原文件,以写的方式打开一个临时文件,一行行的读取原文件内容,修改完后写入临时文件…删掉原文件,将临时文件重命名为原文件名
        • 优点:不会占用过多内存
        • 缺点:在文件修改过程中同一个数据存了两份
import os       

with open('db.txt',mode='rt',encoding='utf-8') as read_f,\
        open('.db.txt.swap',mode='wt',encoding='utf-8') as wrife_f:
    for line in read_f:
        wrife_f.write(line.replace('SB','kevin'))

os.remove('db.txt')         #和上面的import os,os.remove方法删除文件
os.rename('.db.txt.swap','db.txt')     #和上面的import os,os.rename方法修改文件名

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值