day 12

内容概括

  • 引入

  • 文件操作的基本流程

  • 文件的操作模式

    • 控制文件读写的操作模式
    • 控制文件读写内容的模式
  • 操作文件的方法

  • 主动控制文件内指针移动

  • 文件修改

内容详细

  • 引入

    """
    1、什么是文件
        文件是操作系统提供给用户或者说应用程序操作硬盘的一种功能
    
    2、为何要用文件
        读写文件就是在读写硬盘:我们对文件的读写操作都会被操作系统转换成硬盘的读写操作
    
        应用程序-------------》文件对象、文件句柄
        操作系统-------------》文件
        硬件-----------------》硬盘
    
    3、如何用文件
    
    """
    # ps:   decode:编码  encode:解码
    # read().decode    write().encode
    
  • 文件操作的基本流程

    # 由应用程序向操作系统发起系统调用open(),操作系统打开文件,对应一块硬盘空间,并返回一个文件对象赋值给变量f
    f=open('a.txt',mode='rt',encode='utf-8')
    # 调用文件对象下的读/写方法,会被操作系统转换为读/写硬盘的操作
    res = f.read()
    # 向操作系统发起关闭文件的请求,回收系统资源
    f.close
    # 回收应用程序级的变量
    del f  # 但是由于python的自动垃圾回收机制使得我们无需考虑del f
    
    
    
    # 由于老是会忘记关闭文件,回收系统资源,因此python提供了with关键字来帮我们管理上下文
    with open('a.txt',mode='rt',encode='utf-8') as f,\
    	open(r'c:\d.txt',mode='rt'.encode='utf-8') as f1:
            ...
            
    # 注:这里 as f: 后面的\,是因为代码太长,做个换行,'c:\d.txt'前面的r是用来转义的
    # 转义路径中的\
    
  • 文件的操作模式

    • 控制文件读写的操作模式

      # 1.r(默认) 只读模式
      # 2.w 只写模式
      # 3.a 只追加模式
      
      # 以下  '|'  我把它当作指针来表示
      # 1、r模式:只读模式,如果文件不存在则报错,文件存在则文件指针处于文件开头
      with open('a.txt',mode='rt',mode='utf-8') as f:
          print('第一次读'.center(50,'*'))
          print(f.read())  
          # 此时指针位置 xixi|    '|'代表指针位置,并且文件处于打开状态并未关闭
          
      # with open(r'a.txt', mode='rt', encoding='utf-8') as f:
      # 如果这里加了这行代码表示重新打开文件,则能读到xixi
          print('第二次读'.center(50,'*'))
          print(f.read())
          # 因为指针在 xixi|,后面没有内容,因此读不到内容
      # 这里a.txt里的内容为:xixi
      '''
      输出结果:
      ***********************第一次读***********************
      xixi
      ***********************第二次读***********************
      '''
      # 案例:
      # 验证账号和密码
      inp_name = input('请输入账号:').strip()
      inp_password = input('请输入密码:').strip()
      with open(r'user.txt',mode='rt',encoding='utf-8') as f:
          for line in f:
              username,password = line.strip().split(':')
      
              if inp_name == username and inp_password == password:
                  print('login successful')
                  break
          else:
              print('username or password error')
      
      # 2、w模式:只写模式,如果文件存在则创建空文档,文件存在则清空,文件指针处于文件开头
      with open('b.txt,mode='wt',encoding='utf-8') as f:
                f.read()  # 报错 只能写不可读
                print(f.write('ycc')) # 指针指向ycc| ,
                print(f.write('ycc\n'))  #指针指向下一行开头
      # 如果此时我重新运行.py文件(即重新打开b.txt文件),则会清空内容,并重新写入
      
                
      with open(r'b.txt',mode='wt',encoding='utf-8') as f:
          f.write('哈哈哈\n')
          f.write('嘿嘿\n')
      # 此时我先写了代码f.write('哈哈哈\n'),在b.txt文件没有关闭(即没重新运行.py文件的情况下),
      # 写代码f.write('嘿嘿\n'),新的内容会跟在就内容之后
            
                
      # 3.a模式:只追加写,在文件不存在时创建新文档,在文件存在时文件指针会直接跳到末尾
      with open(r'c.txt',mode='at',encoding='utf-8') as f:
          # f.read()  # 不可读 报错
          f.write('切列1\n')
          f.write('切列2\n')
          f.write('切列3\n')
      # 每次重新运行 a模式.py  ,不会清空列表,只会一直添加write()内写的内容
                
      # 强调w模式和a模式的不同
      # 相同:在文件没有关闭的情况下,连续的写入,新写的内容会跟在前面写的内容后
      # 不同:以a模式打开文件不会清空文件内容,指针会移动至文件末尾
      # 案例:
      # 注册功能
       inp_username = input('请输入账号:')
       inp_password = input('请输入密码:')
       with open(r'user.txt',mode='at',encoding='utf-8') as f:
           f.write('{}:{}\n'.format(inp_username,inp_password))
      
      # 文件copy工具
      with open('a.txt',mode='rt',encoding='utf-8') as f1,\
          open('b.txt',mode='at',encoding='utf-8') as f2:
          print(f2.write(f1.read()))
      
    • 控制文件读写内容的模式

      # t(文本模式)(默认):读写都是以字符串为单位的,只适用于文件,必须指定encoding参数
      # b(二进制模式):读写都是以butes为单位的,适用于所有文件的,一定不能指定encoding参数
      
      # t模式上面已经介绍完了(rt,wt,at)
      # 强调:t模式只能用于操作文本文件,无论读写,都是以字符串为单位,而存取硬盘本质都是二进制模式,当我们指定了t模式后,内部帮我们做了编码和解码。
      
      
      # b模式(以什么编码输入就要以相同的编码格式输出)
      with open('1.mp4',mode='rb') as f:
          res = f.read()
      	print(res.decode('utf-8'))  # 这里本来输出的是二进制,需要decode进行解码
      # 例题:文件拷贝
      # 方法一:
      with open('1.mp4',mode='rb') as f1,\
      	open('D:\111.mp4',mode='wb') as f2:
          res = f1.read()  # 将整个文件内容读出
          print(write(res)
      # 方法二:
      with open('1.mp4',mode='rb') as f1,\
      	open('D:\111.mp4',mode='wb') as f2:
                for line in f1:  # 循环遍历,一行一行读出
                	f2.write(line)
                
                
      # 了解 可读可写
      # r+t
      # w+t
      # a+t
      
      # r+b
      # w+b
      # a+b
                
                
      # with open('a.txt',mode='r+t',encoding='utf-8') as f:
      #     print(f.readable())
      #     print(f.writable())
      #     print(f.read())
      #     f.write("22222222222222222222\n")
      
      
      
      # with open('a.txt',mode='w+t',encoding='utf-8') as f:
      #     print(f.readable())
      #     print(f.writable())
                
      
  • 操作文件的方法

    # 重点
    # 1.读操作
    # f.read()  # 读取所有内容,执行完该操作后,指针移至文件末尾
    # f.readline()  # 读取一行内容,指针移至第二行内容开头
    # f.readlines()  # 读取每一行内容,存放于列表中
    # 强调:f.read()和f.readlines()都是一次性读入内容,如果内容过大,会导致内存溢出,
    # 如果想将内容全部读入内存,必须分多次读入,一下有两种方式
    
    # 方法一:
    with open('a.txt',mode='rt',encoding='utf-8') as f:
        for line in f:
            print(line)  # 同一时刻只将一行代码读入内存
    
    # 方法二:
    with open('1.mp4',mode='rb') as f:
        while True:
            res = f.read(1024) # 同一时刻只读入1024个bytes到内存中
            if len(res) == 0:
                break
            print(res)
    
    
    # 2.写操作
    # f.write('111\n222\n')  # 针对文本模式的写
    # f.write('111\n222\n'.encode('utf-8'))  # 针对b模式的写   同时这里本来输出的是二进制,需要encode进行解码
    # f.writelines(['111\n','222\n'])  # 针对文件模式 ,且这里用列表形式输出
    # f.writelines([bytes('111\n',encode='utf-8'),'222\n'.encode('utf-8')])  # 针对b模式
    # 注:这里用了两种方式:
    1、bytes('111\n',encode='utf-8')
    2、'222\n'.encode('utf-8')
    
    
    
    
    # 了解
    f.readable()  # 文件是否可读
    f.writable()  # 文件是否可读
    f.closed  # 文件是否关闭
    f.encoding  # 如果文件打开模式为b,则没有该属性
    f.flush()  # 立刻将文件内容从内存刷到硬盘
    f.name
            
    
  • 主动控制文件内指针移动

    # 文件指针的移动都是bytes为单位的,唯一例外的是t模式下的read(n),n以字符为单位,一个字符=3bytes
    with open('a.txt',mode='rt',encode='utf-8') as f:
        f.read(3)  # 读取3个字符
        
    with open('a,txt',mode='rb') as f:
        f.read(3)  # 读取3个bytes
    
    # 若想读取文件某一特定位置的数据,可用f.seek()主动控制文件内指针的移动
    # f.seek(指针移动的字节数,模式控制)
    # 模式控制(0,1,2三种模式)
    # 0:该模式代表指针移动的字节数是以文件开头为参照的(默认模式)
    # 1:该模式代表指针移动的字节数是以当前所在位置为参照的
    # 2:该模式代表指针移动的字节数是以文件结尾为参照的
    
    # 0模式:
    # hello你好
    # with open('a.txt',mode='rt',encoding='utf-8') as f:
    #     f.seek(3,0)
    #     print(f.tell())  # 查看当前文件指针距离文件开头的位置    3
    #     print(f.read())  # 从第三个字节读到文件末尾           lo你好
    
    # with open('a.txt',mode='rt',encoding='utf-8') as f:
    #     f.seek(6,0)
    #     print(f.tell())  # 查看当前文件指针距离文件开头的位置    6
    #     print(f.read())  # 从第三个字节读到文件末尾           报错
    # 这里报错,因为在t模式下会将读取的内容自动解码,
    # 所以必须保证读取的内容是一个完整的中文数据,否则解码失败报错
    
    # 1模式
    # 123456789
    # with open('d.txt',mode='rb') as f:
    #     f.seek(3,1)  # 从当前位置往后移动3个字节,而此时的当前位置就是文件开头
    #     print(f.tell())  # 查看当前文件指针距离文件开头的位置    3
    #     print(f.read())  # b'456789'
    #     f.seek(4,1)  # 再次从当前位置往后移动3个自己,而此时的文件指针位置在9后面
    #     print(f.tell())  # 9再往后4个bytes,位置为13
    #     print(f.read())  # 此时内容为 b''
    
    # 2模式
    # abc你好
    # with open('a.txt',mode='rb') as f:
    #     f.seek(0,2)     # 参照文件末尾移动0个字节, 即直接跳到文件末尾
    #     print(f.tell()) # 输出结果为:9
    #     f.seek(-3,2)     # 参照文件末尾往前移动了3个字节
    #     print(f.read().decode('utf-8')) # 输出结果为:好
    
  • 文件修改

    '''
    1.硬盘的空间是无法修改的,硬盘中数据的更新都是用新内容覆盖旧内容
    2.内存中的数据是可以修改的
    '''
    # 原内容
    # ycc         江苏         180           1001
    # xix         江苏         165           1002
    # haha        上海         170           1003
    # with open('d.txt',mode='r+t') as f:
    #     f.seek(3)
    #     f.write('aaa')
    # 输出结果:
    # yccaaa      江苏         180           1001
    # xix         江苏         165           1002
    # haha        上海         170           1003
    # 这里只是覆盖硬盘里的内容,并没有修改
    
    # 修改方式一:
    # 将文件一次性全部读入内存,在内存中将文件内容进行修改,再用w模式,将之前的文件清空,将现文件写入
    # 优点:在文件修改过程中同一份数据只有一份
    # 缺点:会过多的占用内存
    # with open('e.txt', mode='rt', encoding='utf-8') as f:
    #     res = f.read()
    # with open('e.txt', mode='wt', encoding='utf-8') as f:
    #     f.write(res.replace('ycc', 'xixi'))
    
    # 修改方式二:
    # 以读的方式打开一个文件,以写的方式打开一个临时文件,用for循环遍历读取每一行的内容,
    # 修改完后写入临时文件,删除原文件,将临时文件重命名
    # 优点:不会占有过多内存
    # 缺点:在文件修改的过程中同一数据存了2份
    # import os
    #
    # with open('e.txt', mode='rt', encoding='utf-8') as read_f, \
    #         open('f.txt', mode='wt', encoding='utf-8') as write_f:
    #     for line in read_f:
    #         write_f.write(line.replace('xixi', 'ycc'))
    # os.remove('e.txt')
    # os.rename('f.txt', 'e.txt')
    
posted @ 2021-06-08 19:41  ccFTD  阅读(41)  评论(0)    收藏  举报