• 文件读写--python基础


    在前面我们学习了变量、序列、对象,在他们中存储的数据是暂时的,程序结束数据就会丢失。为了能够长时间保存数据,需要将数据保存到磁盘文件。
    本篇博客就来介绍如何对磁盘数据进行读写等操作。

    1. 数据读取理论

    在python中要想读取数据,需要先将磁盘文件打开,建立数据传输的通道。

    1.1 打开文件

    打开文件使用open函数,open函数基本语法格式如下:

    file =open(filenam,mode = 'r',buffering = -1, encoding = NOne,errors = None, closefd = True, opener = NOne)
    
    • 1

    open函数用于打开文件并返回流,当打开失败时会出现OSError错误。

    主要用到的参数:

    1)filename: 文件名称
    (1) 文件可以是文本文件或二进制文件
    (2)文件名称需要使用单引号或者双引号括起来
    (3)引号内部有3种情况:
        a. 要打开的文件和当前文件在同一目录下:  可以使用相对路径。
        b. 要打开的文件与当前文件不在同一目录下,必须使用完整的绝对路径
        c. 还可以使用文件描述符。(我还不清楚)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
     2)mode: 文件的打开模式
    
    • 1
    取值说明指针位置
    r以只读方式打开文件文件开头
    r+打开文件后,可以读取文件内容,也可以写入新的内容覆盖原有内容文件开头
    rb+以二进制方式打开文件,且采用读取的方式文件开头
    w以只写方式打开文件文件开头
    w+打开文件后,先清空原有内容,对空文件进行写入文件开头
    wb+以二进制方式打开文件,且采用写入的方式文件开头
    a以追加方式打开文件,文件结尾
    w+打开文件后,先清空原有内容,对空文件进行写入文件结尾
    wb+以二进制方式打开文件,且采用写入的方式文件结尾

    1.2 读取文件

    1.2.1 调用read方法读取

    read函数从open函数返回的流中解码数据并返回结果

    file.read(size = -1)
    
    • 1

    参数含义:

    1) size: 可选参数,指定要读取的字符个数,read采取的是贪婪读取模式,默认值表示读取全部。size的设定可以在面对大文件时,
    避免一次性读取过多内容,可以按照需求设置读取长度。
    注意:read方法读取文件时,是从文件的开头开始读取的,读取完毕指针移到文件末尾。
    
    • 1
    • 2
    • 3

    1.3 写入文件

    python对象提供了write()方法,可以向文件中写入内容,语法格式如下:

    file.write(string)
    
    • 1

    1.4 关闭文件

    打开文件后,需要及时关闭,忘记关闭文件会造成系统资源消耗,且会影响后续文件的访问。文件关闭使用文件对象的close方法实现。语法格式如下:

    file.close()
    
    • 1

    2. 演练

    2.1 读取文件

    2.1.1 mode = 'r’与mode='r+'模式

    使用非二进制的mode = 'r’与mode='r+'模式读取文件

    原文件是这样的
    在这里插入图片描述

    接下来,先演练读取数据,读取数据后要及时调用file.close关闭

    以mode = 'r' 或者mode = 'r+'的打开文件结果如下:
    
    • 1

    在这里插入图片描述

    在这里插入图片描述

    以mode = 'r' 或者mode = 'r+'的方式读取文件:
    
    • 1

    在这里插入图片描述

    在这里插入图片描述

    mode = 'r+' 模式,不仅可以使用read方法读取文件,而且也可以使用write方法写入新的内容。而mode = 'r' 模式为只读模式,不能使用write方法
    
    • 1

    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述

    可以看到,mode ='r+'模式,不仅可以读取数据,而且支持写入数据。但是要注意,当打开文件之后,第一次调用read()方法读取文件后,
    指针在从开头移动到了文件末尾,这时再执行write()方法会在此时指针的位置往后继续写入,而写入之后文件指针在添加了写入内容的
    整个文件的末尾,因此再调用read()函数时,并不能读取到文件内容。
    
    • 1
    • 2
    • 3

    当先写入后读取文件,来看下运行情况:
    在这里插入图片描述
    在这里插入图片描述

    这个文件的运行如下:首先打开文件,指针此时在文件开头,然后调用write()方法,会从指针的位置向后写入write()中的内容:
    已存在文件的r+模式打开;此时指针移动到“开”字后面,而原文件中的“相对人类的欲望而言,资”这几个字符被替换为长度相等的
    “已存在文件的r+模式打开”(write()方法中应该1个汉字占据两个字符),因此下面调用read()方法时,指针从“开”字后面的“源”开始,
    输出:源是稀缺的!!!
    
    • 1
    • 2
    • 3
    • 4
    总结:
    1)以text mode 形式打开的文件返回TextIOWrapper。
    2)open()函数建立了磁盘数据传输的通道,返回流对象。
    3)open()函数执行后,文件指针位于文件开头
    4)read()函数以贪婪模式执行,默认读取全部文件数据
    5)read()函数执行后,文件指针位于文件末尾
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2.1.2 以二进制方式打开文件

    mode = 'rb’或mode=‘rb+’
    同理mode = 'rb’模式是只读模式,无法进行write()方法的写入操作

    在这里插入图片描述

    mode = 'rb+'模式,不仅可以读取文件,而且可以写入文件,但是写入内容必须为字节对象。这里使用
    bytes函数转换。
    在这里插入图片描述
    在这里插入图片描述

    2.2 以写模式打开文件

    2.2.1 以只写模式打开文件

    以只写模式mode = 'w’或者mode = 'wb’模式打开文件,只能进行write()方法的操作,不能进行read()方法操作。
    在这里插入图片描述
    以只写模式,若原文件存在,会先清空原文件内容,再进行写入。

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    2.2.2 以读写方式打开文件

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    总结:
    1) mode = 'w' 或mode = 'wb'模式为只写模式,不能使用read()方法
    2)mode = 'w+'或mode='wb+'模式为读写模式,可以使用read()方法;但是可以看到read()的内容为空,
    这是因为'w'的相关模式在打开文件后,会先清空原有内容,使其转变为空的文件,因此,
    第一次的read()方法输出为空,写入内容后,文件指针在文件末尾,因此,第二次的read()方法输出为空。
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2.3 以追加模式打开文件

    2.3.1 以追加模式打开文件

    在这里插入图片描述
    在这里插入图片描述
    可以看到以mode = 'a’或者mode = 'ab’追加模式打开文件是不能读取文件内容的。

    ecomi = open('C:\\Users\\changyanhua\\Desktop\\testw.txt', mode='a')
    print(ecomi)
    # print(ecomi.read())
    # print('*'*20)
    ecomi.write('花好月圆')
    # ecomi.write(bytes('基本文件操作', 'utf-8'))
    # print(ecomi.read())
    ecomi.close()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    # 相对人类的欲望而言,资源是稀缺的!!!
    ecomi = open('C:\\Users\\changyanhua\\Desktop\\testw.txt', mode='ab')
    print(ecomi)
    # print(ecomi.read())
    # print('*'*20)
    # ecomi.write('花好月圆')
    ecomi.write(('二进制'.encode()))
    # print(ecomi.read())
    ecomi.close()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

    总结:
    1)以追加模式打开的文件不能进行读取操作
    2)文件打开后,文件指针放在文件末尾,新内容写入已有内容之后。
    
    
    • 1
    • 2
    • 3
    • 4

    2.3.2 以读写模式打开

    在这里插入图片描述
    ![在这里插入图片描述](https://img-blog.csdnimg.cn/c28c8b81fad44caa899cf498faa8f49e.png

    在这里插入图片描述
    在这里插入图片描述

    总结:
    1)采用mode = 'a'或者mode='ab'无法调用read()方法
    2)采用mode = 'a+'或者mode='ab+'可以调用read()方法,但是同前面一样的道理,文件指针在文件末尾,所以没有读取到数据。
    
    • 1
    • 2
    • 3
    下面来看以二进制方式打开文件,结果根据mode模式不同而不同:
    
    • 1
    以mode = 'rb',只读二进制格式打开,返回BufferedReader
    
    • 1

    在这里插入图片描述

    以mode = 'wb',采用只写;或者mode = 'ab'追加模式二进制格式打开,返回BufferedWriter
    
    • 1

    在这里插入图片描述
    在这里插入图片描述

    以mode = 'rb+',或者mode = 'wb+'或者mode = 'ab+'读写模式二进制格式打开,返回BufferedRandom
    
    • 1

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    3. 读取文件

    3.1 read()方法

    read函数从open函数返回的流中解码数据并返回结果

    file.read(size = -1)
    
    • 1

    参数含义:

    1) size: 可选参数,指定要读取的字符个数,read采取的是贪婪读取模式,默认值表示读取全部。size的设定可以在面对大文件时,
    避免一次性读取过多内容,可以按照需求设置读取长度。
    注意:read方法读取文件时,是从文件的开头开始读取的,读取完毕指针移到文件末尾。
    
    • 1
    • 2
    • 3

    在这里插入图片描述

    1)结合前面代码可以看到,read()函数默认读取全部字符
    2)还可以通过size指定读取字符的个数:1个汉字算一个字符。
    
    • 1
    • 2

    3.2 read.line()方法

    当文件很大,一次性读取全部内容,容易造成内存不足,可以逐行读取,采用read.line()方法

    在这里插入图片描述

    在这里插入图片描述
    还可以使用readline逐行读取全部内容,判断依据以读取内容是否为空来判断:
    在这里插入图片描述

    # 相对人类的欲望而言,资源是稀缺的!!!
    ecomi = open('C:\\Users\\changyanhua\\Desktop\\ec_test.txt', mode='r')
    print(ecomi)
    i = 0
    
    while True:
        line_con = ecomi.readline()
        print(line_con)
        if line_con == '\n':
            i += 1
            print(i)
        if line_con == '':
            break
    ecomi.close()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在这里插入图片描述
    在这里插入图片描述

    1)中间中间的空白部分读取内容是换行符'\n',并不是空,所以有空白也不影响读取至文件结束。
    2)输出代码中line_con的类型,显示为str;因此readline的返回结果为字符串。
    
    • 1
    • 2

    在这里插入图片描述

    3.3 readlines()方法

    在这里插入图片描述
    在这里插入图片描述

    从代码运行结果可以看出:
    1) readlines读取全部文件内容;
    2)readlines的返回结果为字符串列表,列表的每个元素记录一行内容;
    3)返回内容不仅包括文本内容,还包括每行的换行符: \n;
    
    • 1
    • 2
    • 3
    • 4

    对于结果列表,使用for循环遍历,可以得到与read()方法一样的结果

    ecomi = open('C:\\Users\\changyanhua\\Desktop\\ec_test.txt', mode='r')
    print(ecomi)
    
    lin_cons = ecomi.readlines()
    for item in lin_cons:
        print(item)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述
    在这里插入图片描述

    4. 文件指针

    4.1 移动文件指针:seek()

    前面在读写函数时,经常发生文件指针在文件结尾,导致读取内容为空的情况,如果想要得到内容或者想要读取部分内容,可以移动文件指针的位置,使用seek()方法

    file.seek(offset[,whence])
    
    • 1

    参数含义:

    1) offset: 移动的字符个数,seek()方法中,汉字占两个字符
    2)whence: 指定从什么位置开始计算。
    (1)0: 从文件头开始
    (2)1:从当前位置开始
    (3)2: 从文件末尾开始
    
    • 1
    • 2
    • 3
    • 4
    • 5

    不指定移动字符的个数,默认移动整个文件字符的长度:

    # 相对人类的欲望而言,资源是稀缺的!!!
    ecomi = open('C:\\Users\\changyanhua\\Desktop\\testw.txt', mode='r+')
    print(ecomi)
    
    cons = ecomi.read()
    print(cons)
    print('*'*20)
    ecomi.write('\n移动文件指针')
    # 未人为移动指针时:
    pre_cons = ecomi.read()
    print(pre_cons)
    print('*'*20)
    ecomi.seek(0)
    # 主动移动指针后:
    aft_cons = ecomi.read()
    print(aft_cons)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    在这里插入图片描述
    指定移动字符的长度(汉字及其符号,占两个字符长度)

    # 相对人类的欲望而言,资源是稀缺的!!!
    ecomi = open('C:\\Users\\changyanhua\\Desktop\\testw.txt', mode='r+')
    print(ecomi)
    
    cons = ecomi.read()
    print(cons)
    
    count = 2* len(cons)
    print(count)
    
    print('*'*20)
    ecomi.write('\n移动文件指针')
    # 未人为移动指针时:
    pre_cons = ecomi.read()
    print(pre_cons)
    
    print('*'*20)
    ecomi.seek(count, 0)
    # 主动移动指针后:
    aft_cons = ecomi.read()
    print(aft_cons)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    在这里插入图片描述

    如果文件不是使用二进制方式打开是只能从文件开头开始计算,即:whence取值只能为0,否则会出现异常:
    
    • 1

    在这里插入图片描述

    4.2 返回文件指针位置:tell()

    在这里插入图片描述
    在这里插入图片描述

    关键点:
    1)打开文件后文件指针位置在开头0
    2)一个汉字占两个字符
    3)每行结尾的换行符'\n'占两个字符
    
    • 1
    • 2
    • 3
    • 4
  • 相关阅读:
    计算机毕业设计Java教评系统(源码+系统+mysql数据库+lw文档)
    java Python+Django的大学生提问论坛系统-在线答疑系统
    【图像分割】基于区域的重叠椭圆拟合实现细胞分割附matlab代码
    失控的返回值
    ICCV2021 Exploring Cross-Image Pixel Contrast for Semantic Segmentation (Oral)
    第十章-项目沟通管理
    oracle 执行计划查看常用sql
    【ZLM】花屏现象记录
    第三章 ArcGIS Pro创建 python 脚本工具(五)
    腾讯的Tendis用了这么多牛逼技术,能否干掉Redis?
  • 原文地址:https://blog.csdn.net/chongbaikaishi/article/details/125424206