• 文件操作


    一、IO操作的概述

      文件操作就是一种IO操作,所以在了解文件系统前首先要了解什么是IO操作。

     I/O在计算机中是指Input/Output,也就是Stream(流)的输入和输出。这里的输入和输出是相对于内存来说的,Input Stream(输入流)是指数据从外(磁盘、网络)流进内存,Output Stream是数据从内存流出到外面(磁盘、网络)。程序运行时,数据都是在内存中驻留,由CPU这个超快的计算核心来执行,涉及到数据交换的地方(通常是磁盘、网络操作)就需要IO接口。

    操作系统屏蔽了底层硬件,向上提供通用接口。因此,操作I/O的能力是由操作系统的提供的,每一种编程语言都会把操作系统提供的低级C接口封装起来供开发者使用,Python也不例外。

    二、文件操作

      1. 文件操作的接口

        python中有一个内置函数open(),我们可以直接通过接收"文件路径"以及“文件打开模式”等参数获取我们的文件对象(这就是我们在程序中要操作的文件对象),并返回该文件对象的文件描述符.这样我们就可以对文件对象进行读写操作了。

      2. 文件操作的流程  

    # 打开文件,获取文件描述符
    f = open('a.txt', 'r', encoding='utf8')
    
    # 操作文件描述符--读/写
    res = f.read()
    print(res)
    
    # 关闭文件
    f.close()

      那么文件系统在计算机中是怎么实现的呢?

       3. 文件的资源回收

    文件读写操作完成后,应该及时关闭。一方面,文件对象会占用操作系统的资源;另外一方面,操作系统对同一时间能打开的文件描述符的数量是有限制的,如果不及时关闭文件,还可能会造成数据丢失。因为我将数据写入文件时,操作系统不会立刻把数据写入磁盘,而是先把数据放到内存缓冲区异步写入磁盘。当调用close方法时,操作系统会保证把没有写入磁盘的数据全部写到磁盘上,否则可能会丢失数据。

      

      python还提供了with关键字帮助我们管理上下文,自动关闭文件,这样我们就可以不用手动关闭文件了。

    with open('a.txt', 'a',encoding='utg8') as f:
        res = f.read()
        print(res)

    三、文件的打开模式

    模式描述
    t 文本模式 (默认)。
    x 写模式,新建一个文件,如果该文件已存在则会报错。
    b 二进制模式。
    + 打开一个文件进行更新(可读可写)。
    U 通用换行模式(Python 3 不支持)。
    r 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。相当于rt
    rb 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。一般用于非文本文件如图片等。
    r+ 打开一个文件用于读写。文件指针将会放在文件的开头。
    rb+ 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。一般用于非文本文件如图片等。
    w 打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。相当于wt
    wb 以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如图片等。
    w+ 打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
    wb+ 以二进制格式打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如图片等。
    a 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。相当于at
    ab 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
    a+ 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。
    ab+ 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。

    r+、w+和a+的区别 : 

    • r+会覆盖当前文件指针所在位置的字符,如原来文件内容是"Hello,World",打开文件后写入"hi"则文件内容会变成"hillo, World"
    • w+与r+的不同是,w+在打开文件时就会先将文件内容清空,感觉和w没啥区别啊
    • a+与r+的不同是,a+只能写到文件末尾(无论当前文件指针在哪里)

    四、文件读写与字符编码

      `在使用open()方法打来一个文件时,可以指定字符的编码,如果我们没有为open指定编码,那么打开文件的默认编码很明显是操作系统说了算了,操作系统会用自己的默认编码去打开文件,在windows下是gbk,在linux下是utf-8。 这就用到了上节课讲的字符编码的知识:若要保证不乱码,文件以什么方式存的,就要以什么方式打开。

      详细可以看一下博客https://www.cnblogs.com/yyds/p/6186621.html

    五、python文件读取的相关方法

    1.文件的操作方法

    方法描述
    read() 一次读取文件所有内容,返回一个str
    read(size) 每次最多读取指定长度的内容,返回一个str;在Python2中size指定的是字节长度,在Python3中size指定的是字符长度
    readlines() 一次读取文件所有内容,按行返回一个list
    readline() 每次只读取一行内容

    1. read()方法     ---- 读取所有内容,光标移动到文件末尾

    f = open('a.txt', 'r', encoding='utf8')
    res = f.read()
    print(res)
    print(type(res)) # 返回一个字符串类型
    f.close()
    
    “””
    匆匆那年我们 究竟说了几遍 再见之后再拖延
    可惜谁有没有 爱过不是一场 七情上面的雄辩
    <class 'str'> “””

    2. read(szie) 

    • 文件打开方式为文本模式时,代表读取size个字符
    • 文件打开方式为b模式时,代表读取size个字节

    3. readlines()

    with open('a.txt', 'r', encoding='utf8') as f:
        res = f.readlines()
        print(res)
        print(type(res))
    
    “””
    ['匆匆那年我们 究竟说了几遍 再见之后再拖延
    ', '可惜谁有没有 爱过不是一场 七情上面的雄辩']
    <class 'list'>
    
    “””

    这种方式的缺点与read()方法是一样的,都是会消耗大量的内存空间.前面讲过打开的文件对象也是一个迭代器,所以我们可以通过迭代器对文件进行读取.

    with open('a.txt', 'r',encoding='utf8') as f:
        for line in f:
            print(line)

    4. readline()

    with open('a.txt', 'r', encoding='utf8') as f:
        res = f.readline()
        print(res)
        print(type(res))
    
    """
    匆匆那年我们 究竟说了几遍 再见之后再拖延
    <class 'str'> 
    """

    2. 此外,还要两个个与文件指针位置相关的方法

    方法描述
    seek(n) 将文件指针移动到指定字节的位置
    tell() 获取当前文件指针所在字节位置

    注意这两种种方法在文件内光标移动都是以字节为单位

    1. seek()

      seek有三种移动方式0,1,2,其中1和2必须在b模式下进行,但无论哪种模式,都是以bytes为单位移动的

    • 0 模式 : 默认模式,表示指针移动的字节数是以文件开头为参照 
    f = open('a.txt', 'r', encoding='utf8')
    f.seek(6, 0)
    print(f.tell())
    print(f.read())
    f.close()
    
    """
    6
    那年我们 究竟说了几遍 再见之后再拖延
    可惜谁有没有 爱过不是一场 七情上面的雄辩
    """

    需要注意的是,在t模式下会将读取的文件自动解码,所以我们必须保证读取的内容是一个完整的数据(中文占3个字节,数字字母占一个字节),否则会报错

    f = open('a.txt', 'r', encoding='utf8')
    f.seek(5, 0)
    print(f.tell())
    print(f.read())
    f.close()
    
    """
    UnicodeDecodeError: 'utf-8' codec can't decode byte 0x86 in position 0: invalid start byte
    """
    • 1模式:表示指针移动的字节数是以当前所在位置为参照,必须是以b的形式打开
      with open('a.txt', 'rb') as f:
          f.seek(5, 1) # 当前位置为文件开头
          print(f.tell())
          f.seek(7, 1) # 当前位置为5
          print(f.tell())
          print(f.read().decode('utf8'))
      
      """
      5
      12
      我们 究竟说了几遍 再见之后再拖延
      可惜谁有没有 爱过不是一场 七情上面的雄辩
      """
    • 2模式: 表示指针移动的字节数是以文件末尾位置为参照

       指针从后面往前面移动的话,步长要为负数

    with open('a.txt', 'rb') as f:
        f.seek(-6, 2) # 文件从末尾向前移动了6个字节
        print(f.tell())
        print(f.read().decode('utf8'))
    
    """
    114
    雄辩
    """

     


    3. file类的其他方法:

    方法描述
    flush() 刷新缓冲区数据,将缓冲区中的数据立刻写入文件
    next() 返回文件下一行,这个方法也是file对象实例可以被当做迭代器使用的原因
    truncate([size]) 截取文件中指定字节数的内容,并覆盖保存到文件中,如果不指定size参数则文件将被清空; Python2无返回值,Python3返回新文件的内容字节数
    write(str) 将字符串写入文件,没有返回值
    writelines(sequence) 向文件写入一个字符串或一个字符串列表,如果字符串列表中的元素需要换行要自己加入换行符
    fileno() 返回一个整型的文件描述符,可以用于一些底层IO操作上(如,os模块的read方法)
    isatty() 判断文件是否被连接到一个虚拟终端,是则返回True,否则返回False

    六、文件的修改操作

      因为文件数据是存储在磁盘或硬盘上的,所以无法被修改,但如果真的想要修改一个文件,可以通过覆盖的形式来实现,这也是我们平时看到的修改文件的方法.

    import os
    
    with open('a.txt', encoding='utf8') as read_f, open('.a.txt.swap', 'w', encoding='utf8') as write_f:
        data = read_f.read()  # 全部读入内存,如果文件很大,会很卡
        data = data.replace('再见', '你好')  # 在内存中完成修改
    
      # 可以再优化一下,利用迭代器将文件一行行读入和修改
      """
       for line in read_f: 
          data = line.replace('再见', '你好') 
          write_f.write(data)  
      """
    
    
        write_f.write(data)  # 一次性写入新文件
    
    os.remove('a.txt')
    os.rename('.a.txt.swap', 'a.txt') # 将新文件改名为旧文件名,从而达到覆盖
  • 相关阅读:
    CF1324F Maximum White Subtree
    CF1204C Anna, Svyatoslav and Maps
    CF1187E Tree Painting
    CF1304E 1-Trees and Queries
    深入探究jvm之类装载器
    深入探究jvm之GC的算法及种类
    深入探究jvm之GC的参数调优
    spring源码解析之AOP原理
    spring注解扫描组件注册
    cas-client单点登录客户端拦截请求和忽略/排除不需要拦截的请求URL的问题
  • 原文地址:https://www.cnblogs.com/liangweijiang/p/11865238.html
Copyright © 2020-2023  润新知