• 文件操作


    1. 学前三问

    1.1 什么是文件 ?

    文件是操作系统提供给用户/应用程序操作硬盘的一种虚拟的概念/接口。

    用户/应用程序
    操作系统(文件)  操作系统会把对用户/应用程序文件功能的调用转成具体的硬盘操作
    计算机硬件(硬盘)
    

    1.2 为何要用文件

    用户/应用程序可以通过文件将数据永久保存的硬盘中,即操作文件就是操作硬盘。

    用户/应用程序直接操作的是文件,对文件进行的所有操作,都是在向操作系统发送系统调用,然后再由操作将其

    转换成具体的硬盘操作。

    1.3 如何用文件:open( )

    1.3.1 控制文件读写内容的模式:t和b

    强调: t和b不能单独使用,必须跟r/w/a连用,默认就是t, t代表text,通常不写

    t文本(默认的模式)

    1. 读写都以str(unicode)为单位
    2. 文本文件
    3. 必须指定encoding='utf-8'

    b二进制/bytes

    • 一般是一些音频文件或者视频文件

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

    • r 只读模式
    • w 只写模式
    • a 只追加写模式
    • +: r+, w+, a+ 在原来模式的基础上只读的变可读可写,可写的变可写可读

    2. 文件操作的基本流程

    2.1 打开文件

    open("文件路径")
    open("C:acd.txt")  # 但是(右斜杠)在字符串中转义的作用
                            # 如果文件夹叫nb,那写成路径
    b在字符串中就是换行符的意思了
    

    2.1.1 如何取消转义?

    • 字符串前+r,eg:r"C:a bd.txt"
    • 用左斜杠代替右斜杠,open功能自动会把左斜杠替换成右斜杠

    2.1.2 路径分割符

    • win下默认的路径分隔符是右斜杠
    • linux下默认的路径分隔符是左斜杠/

    2.1.3 绝对路径和相对路径

    绝对路径就是文件的全部路径,从开始的盘符一直写到该文件。

    open(r'E:projectpythons29codeday111.打开文件.py')
    

    相对路径就是以当前文件所在的文件夹为基础,然后找文件,所以也只能找到同文件夹下的文件

    image-20200811163302623

    2.2 操作文件

    # 1. 打开文件,由应用程序向操作系统发起系统调用open(...),
    #    操作系统打开该文件,对应一块硬盘空间,并返回一个文件对象赋值给一个变量f
    f=open('a.txt',moder='r',encoding='utf-8') #默认打开模式就为r
    
    # 2. 调用文件对象的读/写方法,会被操作系统转换为读/写硬盘的操作
    data=f.read()  # 读取文件内容,将硬盘中的二进制数据读取到内存中 --> t控制将二进制转换成字符
    

    image-20200811164602250

    2.3 关闭文件

    打开一个文件包含两部分资源:应用程序的变量f和操作系统打开的文件。在操作完毕一个文件时,必须把与该文

    件的这两部分资源全部回收,回收方法为:

    1、f.close() #回收操作系统打开的文件资源,一旦关闭就不能操作了,但是f变量还在
    2、del f #回收应用程序级的变量,一般我们不用写。
    

    其中del f一定要发生在f.close( ) 之后,否则就会导致操作系统打开的文件无法关闭,白白占用资源, 而python

    自动的垃圾回收机制决定了我们无需考虑del f,这就要求我们,在操作完毕文件后,一定要记住f.close( )。

    2.4 with上下文管理器

    with上文帮你打开文件,下文就是帮你自动关闭文件.

    with open('a.txt',mode='rt') as f1:
        res = f1.read()   # 读取文件内容,硬盘的搬运工
        print(res)
    
    # f1称之为文件对象/文件句柄,就是用来控制文件的
    # 当with语句的代码块执行完毕后会自动执行f.close()
    
    # 打开多个文件
    with open('a.txt',mode='rt') as f1,open('b.txt',mode='rt') as f2:
    #with open('a.txt',mode='rt') as f1,
    #   open('b.txt',mode='rt') as f2:   通过右斜杠将一句代码换行写
        res1 = f1.read()   # 读取文件内容
        res2 = f2.read()   
        print(res1)
        print(res2)
    

    2.5 指定操作文件的字符编码

    open功能还有一个参数就是encoding='解码格式'

    with open(r'a.txt', mode='rt',encoding='utf-8') as f1:
        res = f1.read()   # t模式会将f.read()读出来的结果解码成unicode
        print(res, type(res))
        
        
    # 内存: utf-8格式的二进制 ----> 解码 ---->  unicode
    # 硬盘(a.txt内容: utf-8格式的二进制)
    

    如果你不指定encoding参数的话,操作系统会使用自己的默认编码进行解码。

    • mac/linux utf-8
    • windows gbk

    3. 文件的操作模式

    3.1 控制文件操作的三种模式

    r(默认的):只读
    w:只写
    a:只追加写
    

    3.1.1 r 模式的使用

    r (默认的操作模式):只读模式,当文件不存在时,会报错。

    with open(r'd.txt', mode='rt',encoding='utf-8') as f1:
        res = f1.read()
        print(res, type(res))
        
    # 运行结果:
    Traceback (most recent call last):
      File "E:/project/python/s29code/day11/2.r模式.py", line 1, in <module>
        with open(r'd.txt', mode='rt',encoding='utf-8') as f1:
    FileNotFoundError: [Errno 2] No such file or directory: 'd.txt'
    

    当文件存在时,文件指针跳到开始位置,所以当我们f.read()时会把文件指针从头读到尾,即一次性

    把文件内容全部从硬盘加载到内存中。注意:大文件不能这样读,如果内容过大,会撑爆内存

    # a.txt
    你好啊
    
    with open(r'a.txt', mode='rt',encoding='utf-8') as f1:
        res = f1.read() # 把所有内容从硬盘读入内存
        print(res) # 你好啊  
    

    3.1.2 w模式的使用

    w模式,是只写模式,当文件不存在的时候,用w模式打开的话,会自动在该路径创建一个新的文件。

    当文件存在时,w模式会先清空原来的内容,指针位于开始位置,然后再写内容。

    with open(r'e.txt', mode='w',encoding='utf-8') as f1:
        f1.write("你好")
    

    注意:w模式不是覆盖,可以自己尝试一下,假设原文件的内容很多,你用w模式打开,然后只写一个字符

    试试。

    image-20200819165616241

    image-20200819165629041

    image-20200819165648668

    但是如果我们用w模式没有关闭,连续写入内容的话,不会清空之前的内容,并紧跟在旧的内容后面。

    with open('b.txt',mode='w',encoding='utf-8') as f:
        f.write('大笨蛋
    ')
        f.write("大傻子
    ")
        f.write("二杆子")
        
    # b.txt
    大笨蛋
    大傻子
    二杆子
    

    3.1.3 a模式的使用

    a模式是只追加写模式,当文件不存在时,和w模式一样,会创建新文件。

    当文件存在的时候,a模式打开文件,不会清空原文件的内容,指针会自动移到文件末尾。

    with open('c.txt',mode="a",encoding="utf-8") as f:
        f.write('我是第一行
    ')
        
    # c.txt
    我是第一行
    

    当文件没有关闭的情况,用a模式持续写入的话,是和w模式一样的,新内容会紧跟旧内容的后面

    with open('c.txt',mode="a",encoding="utf-8") as f:
        f.write('我是第一行
    ')
        f.write('我是第二行
    ')
        f.write('我是第三行
    ')
        f.write('我是第四行
    ')
        
    # c.txt
    我是第一行
    我是第二行
    我是第三行
    我是第四行
    

    a模式和w模式的异同点:

    • 相同点:只能写,不能读,当文件没有关闭时,连续写入,新内容紧跟在就内容之后
    • 不同点:a模式打开已存在的文件,不会清空原文件内容,指针自动移动到文件末尾

    w模式和a模式的应用场景:

    • w模式一般用于新文件的保存,比如copy文件底层就是把一个文件读出来,然后用w写入到新文件

    • a模式则是适用于在原文件的基础上写新内容,比如记录日志,用户注册记录文件

    3.1.4 了解+模式

    +模式,不能单独使用,只能和r,w或a模式一起使用

    • r+ 读写模式,基准是r模式,当文件不存在时,用r+打开会报错,指针在开头。
    • w+ 写读模式,基准是w模式,文件不存在会创建文件,文件存在同样会清空原文件
    • a+ 追加读模式,基准是a模式,文件不存在会创建文件,指针在末尾

    3.1.5 提一嘴x模式

    x模式,只写模式,当文件不存在的时候会创建新文件,指针在文件开头,但是当文件存在的时候会直接报错

    # d.txt 已经存在的文件
    with open('d.txt',moder="x",encoding="utf-8") as f:
        f.write("你好")
    
    Traceback (most recent call last):
      File "E:/project/python/s29code/day11/5.x模式.py", line 1, in <module>
        with open('d.txt',mode='x',encoding='utf-8') as f:
    FileExistsError: [Errno 17] File exists: 'd.txt'    
    

    3.2 控制文件内容的两种模式

    大前提: tb模式均不能单独使用,必须与r/w/a之一结合使用
    t(默认的):文本模式

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

    b:二进制模式:

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

    3.2.1 t 模式

    # t 模式:如果我们指定的文件打开模式为r/w/a,其实默认就是rt/wt/at
     with open('a.txt',mode='rt',encoding='utf-8') as f:
         res=f.read() 
         print(type(res)) # 输出结果为:<class 'str'>
    
     with open('a.txt',mode='wt',encoding='utf-8') as f:
         s='abc'
         f.write(s) # 写入的也必须是字符串类型
    
    #强调:t 模式只能用于操作文本文件,无论读写,都应该以字符串为单位,而存取硬盘本质都是二进制的形式,当指定 t 模式时,内部帮我们做了编码与解码
    
    # 如果我们用t模式打开视频文件的话
    with open('a.mp4',mode='rt',encoding='utf-8') as f:
        ...   # ...  == pass 这样并不会报错,因为我们只是调用了操作系统的接口,告诉他用rt打开文件
              # 以后用utf-8对读入内存的文件进行解码,但是我们还没有读/写文件,只是打开文件,所以不报错
    

    3.2.2 b模式

    同样b模式也是不能单独使用的,必须和r、w、a配合使用,t模式只针对字符文件,而b模式是针对所有文件,包

    包括文本文件,但是一定要注意不能指定encoding参数,否则报错。

    with open('a.jpg',mode='rb') as f:
        res = f.read()   # 硬盘的二进制读入内存->b模式下,不做任何转换,直接读入内存
        print(res,type(res)) # bytes类型 -> 当成二进制
        # b'xffxd8xffxe0x00x10JFIFx00x01x01x00x00x01x00x01x00x0C
        # <class 'bytes'>
        
    # 理论上我们应该读出来的是物理层间的010101这种,但是如果以这种显示的话,不利于阅读,以及操作数据
    # 所以python对读出来的内容做了转换,是16进制的显示,平常我们就把当成二进制来看就行了.
    
    with open('b.txt',mode='rb') as f:
        res = f.read()       # 把躺在硬盘的二进制直接读出来,不做任何转换
        print(res,type(res)) 
        print(res.decode('utf-8')) # 文件是以utf-8编码格式存的,可以进行字符解码
    

    4. 循环读取文件的两种方式

    4.1 for循环一行一行的读

    for循环不但可以循环那些基础数据类型,也可以循环文件句柄, 每次循环,以行为单位

    但是for循环有个局限

    # t模式
    with open('b.txt',mode='r',encoding='utf-8') as f:
        for line in f:
            print(line)
            
    
    # 打印内容:        
    # 是可拨打发红包测
    
    # 我付款金额日本
    
    # 费劲儿家人
    
    # b模式
    with open('b.txt',mode='rb') as f:
        for line in f:
            print(line)
            
    
    # 打印内容:
    b'xe6x98xafxe5x8fxafxe6x8bxa8xe6x89x93xe5x8fx91xe7xbaxa2xe5x8cx85xe6xb5x8b
    '  # 
     --> 换行符
    b'xe6x88x91xe4xbbx98xe6xacxbexe9x87x91xe9xa2x9dxe6x97xa5xe6x9cxac
    '
    b'xe8xb4xb9xe5x8axb2xe5x84xbfxe5xaexb6xe4xbaxba
    '
    b'xe4xbbx98xe9x87x91xe9xa2x9dxe6x97xa5xe5x93xa6xe5x9bx9exe9xa1xbe'
    

    4.2 while循环

    之前就说过for循环能实现的,while循环也能实现,循环读取文件也是可以的

    # t模式和b模式都适用
    with open('b.txt',mode='rb') as f:
        while 1:
            content = f.read(1024) # 可以指定读取文件内容的大小,以字节为单位
            if not content:
                break
            print(content)
    

    4.3 小练习

    文件拷贝小程序,要求:字符文件和文本文件都适用。5.

    file_path = input('请输入要拷贝的文件的绝对路径:')
    new_file_path = input('请输入新文件的绝对路径:')
    with open(file_path, mode='rb') as f, 
            open(new_file_path, mode='wb') as f1:
        for line in f:
            f1.write(line)
    

    5. f 的常用方法

    5.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:
            data=f.read(1024) # 同一时刻只读入1024个Bytes到内存中
            if len(data) == 0:
                break
            print(data)
    
    # 写操作
    f.write('1111
    222
    ')  # 针对文本模式的写,需要自己写换行符
    f.write('1111
    222
    '.encode('utf-8'))  # 针对b模式的写,需要自己写换行符
    f.writelines(['333
    ','444
    '])  # 迭代的将列表的元素写入文件
    f.writelines([bytes('333
    ',encoding='utf-8'),'444
    '.encode('utf-8')]) #b模式
    

    5.2 了解操作

    f.readable()  # 文件是否可读
    f.writable()  # 文件是否可读
    f.closed    # 文件是否关闭
    f.encoding  # 如果文件打开模式为b,则没有该属性
    f.flush()   # 立刻将文件内容从内存刷到硬盘,一般情况下当所有写操作完毕后,才会写入硬盘,但是我们             # 可以用flush强制写到硬盘
    f.name      # 返回文件名称
    

    6. 文件指针的移动

    f.seek(n,模式) n指的是移动的字节个数

    f.tell( ) 返回文件指针当前位置

    指针移动的单位都是以字节(bytes)为单位

    只有一种情况特殊:
    t模式下的read(n) n代表字符的个数

    强调: t模式下只能用0模式,b模式下0,1,2都可以用

    6.1三种模式

    模式:
    0:参照物是开头位置
    1:参照物是当前位置
    2:参照物是文件末尾
    

    6.1.1 0模式

    with open(r'a.txt', mode='rt', encoding='utf-8') as f:
        f.seek(6, 0)
        f.seek(3,0)
        # f.seek(3, 1) # 报错
        res = f.read()
        print(res)
    

    6.1.2 1模式

    with open(r'a.txt', mode='rb') as f:
    	f.seek(6, 1)
    	f.seek(3,1)
        #f.seek(300, 1)  # 向右可以无限移动
        # print(f.read())
        res = f.tell()
        print(res)
    

    6.1.3 2模式

    with open(r'a.txt', mode='rb') as f:
        f.seek(-6, 2)
        f.seek(-3, 2)
        # f.seek(-30, 2) # 超过了最大的移动距离
    
        # f.seek(0, 0)
        # f.seek(-1, 0) # 报错,开头无法再向左移动了
        
        res = f.tell() # 返回文件指针的时候都是从左向右数
        print(res)
    

    6.1.4 小作业

    # 写一个动态更新显示最新日志的一个小程序
    import time
    
    with open(r'a.txt', mode='rb') as f:
        # 将指针跳到文件末尾
        f.seek(0, 2)
        while 1:
            res = f.readline()
            if len(res) == 0:
                time.sleep(0.5)
            else:
                print(res.decode(), end='')
                
    # 追加日志的程序
    with open(r'a.txt',mode='a+',encoding='utf-8') as f:
        f.write('20201120 张三消费1000元
    ')
    

    6.2 修改文件的两种方式

    首先补充一个知识点,就是硬盘的数据是不能修改的,内存的数据是可以修改的。比如有一个文本文件,里面有

    数据:张三 北京大学 大一学生,你想修改成 张三 男 20 北京大学 大一学生。平常我们用的文本编辑器是可以

    直接修改的。但是你用python代码试一下看一下结果。

    with open(r'a.txt',mode='r+t',encoding='utf-8') as f:
        f.seek(10,0) # 指针移动到张三后面
        f.write('男 20')
    
    # 当你再次打开文件你会发现 男 20会把北京大学覆盖了
    

    原因是硬盘不支持修改,或者说成是追加。如果一块数据发生移动,那么在它后面的所有数据都会移动,那么每次

    修改文件都会产生这种问题。所以硬盘只能写不能中间插入。而我们平常用的文本编辑器只是把内存中的所有修改

    后的数据再保存到硬盘上。

    6.2.1 第一种方式:

    with open( 'c.txt' ,mode='rt',encoding='utf-8' ) as f:
    	res = f.read ( )
    	data = res.replace( 'alex' , 'dsb')
        print(data)
    with open( 'c.txt' ,mode='wt',encoding='utf-8' ) as f1:
    	f1.write(data)
    

    6.2.2 第二种方式:

    import os
    
    with open(r'c.txt', mode='r', encoding='utf-8') as f, 
            open(r'.c.txt.swap', mode='w', encoding='utf-8') as f1:
        # .原文件名.swap 是linux中的临时交换的文件命名
        for line in f:
            data = line.replace('alex', 'dsb')
            f1.write(data)
    os.remove('c.txt')  # 删除原文件
    os.rename('.c.txt.swap', 'c.txt')  # 对新文件重命名
    
  • 相关阅读:
    nginx搭建文件服务器
    Server.MapPath("/")
    Server.MapPath("/")
    消息钩子函数入门篇
    消息钩子函数入门篇
    SQL Server 2008收缩日志文件dbcc shrinkfile参数说明
    SQL Server 2008收缩日志文件dbcc shrinkfile参数说明
    线性代数——第一章:行列式——§1.1 行列式的定义
    线性代数——第一章:行列式——§1.1 行列式的定义
    ZYAR20A 亚克力2驱 蓝牙 298寻迹避障机器人 —— 程序目录
  • 原文地址:https://www.cnblogs.com/xcymn/p/14019921.html
Copyright © 2020-2023  润新知