0%

38、文件操作.md

一、基础概要

1、文件的概念和作用

我们以前操作的数据都是在程序中提前写死的, 但是在实际开发中这是远远不够的.很多时候我们都需要对存储在计算中文件内的数据进行处理, python 提供了一系列的对文件操作的 api

2、什么是文件

计算机的文件,就是存在在某种长期存储设备上的一段数据

长期存储设备包括:硬盘,U盘,移动硬盘,光盘。。。

3、文件的作用:

将数据长期保存下来,在需要的时候使用

大家应该听说过一句话:“好记性不如烂笔头”。

不仅人的大脑会遗忘事情,计算机也会如此,比如一个程序在运行过程中用了九牛二虎之力终于计算出了结果,试想一下如果不把这些数据存放起来,相比重启电脑之后,“哭都没地方哭了”

可见,在把数据存储起来有做么大的价值

使用文件的目的:

就是把一些存储存放起来,可以让程序下一次执行的时候直接使用,而不必重新制作一份,省时省力

4、文件的存储方式

在计算机中,文件是以二进制的方式保存在磁盘上的

文本文件和二进制文件

文本文件

​ 可以使用文件编辑软件查看

​ 本质上还是一个二进制文件

​ 例如:python的源程序

二进制文件

​ 保存的内容不是给人直接阅读的,而是提供给其他软件使用的

​ 例如:图片文件,音频文件,视频文件等等

​ 二进制文件不能使用文本编辑软件查看

二、文件的基本操作

1、概要

读写文件是最常见的 IO 操作。通常,我们使用 input 从控制台读取输入,使用 print 将内容输出到控制台。实际上,我们也经常从文件读取输入,将内容写到文件。

2、打开文件(open)

1、读文件主要分为三个步骤

  1. 打开文件
  2. 读取内容
  3. 关闭文件

2、语法格式

  1. 格式一

    1
    2
    3
    4
    5
    6
    try:
    f = open('xxx/xxx.txt', 'r') # 打开文件
    data = f.read() # 读取文件内容
    finally:
    if f:
    f.close() # 确保文件被关闭
  2. 格式二(推荐)

    1
    2
    3
    with open('xxx/xxx.txt', 'r') as f:
    data = f.read()
    # 这种方式很简洁,而且还能在出现异常的情况下自动关闭文件

3、参数说明

  1. open函数

    1
    open(file, mode='r', buffering=None, encoding=None, errors=None, newline=None, closefd=True)
  2. file

    操作的文件

    1
    2
    3
    4
    5
    6
    7
    #相对路径
    with open('test.txt', 'r', encoding='utf-8') as f:
    pass

    #绝对路径
    with open('/Users/zhangwei/work/test.txt', 'r', encoding='utf-8') as f:
    pass
  3. mode

    打开文件的模式

    • r ,只读模式【默认 】文件的指针将会放在文件的开头
    • w,只写模式【不可读;不存在则创建;存在则清空内容;】如果该文件已存在则打开文件,并从开头开始编 辑,即原有内容会被删除。如果该文件不存在,创建新文件。
    • +, 只写模式
    • a, 追加模式【可读; 不存在则创建;存在则只追加内容;】文件指针将会放在文件的结尾

    “+” 表示可以同时读写某个文件

    • r+, 读写【可读,可写】
    • w+,写读【可读,可写】
    • x+ ,写读【可读,可写】
    • a+, 写读【可读,可写】

    “b”表示以字节的方式操作

    • rb 或 r+b
    • wb 或 w+b
    • xb 或 w+b
    • ab 或 a+b

    注:以b方式打开时,读取到的内容是字节类型,写入时也需要提供字节类型

  4. buffering

    表示文件在读取操作时使用的缓冲策略。

    • 0:代表buffer关闭(只适用于二进制模式)
    • 1:代表line buffer(只适用于文本模式)
    • >1:表示初始化的buffer大小
  5. encoding

    表示读写文件时所使用的的文件编码格式,如果未正确指定编码,有可能报错

  6. errors

    参数表示读写文件时碰到错误的报错级别。常见的报错基本有:

    • 'strict' 严格级别,字符编码有报错即抛出异常,也是默认的级别,errors参数值传入None按此级别处理.
    • 'ignore' 忽略级别,字符编码有错,忽略掉.
    • 'replace' 替换级别,字符编码有错的,替换成?
  7. newline

    表示用于区分换行符(只对文本模式有效,可以取的值有None,’\n’,’\r’,’’,’\r\n’)

3、file对象

  1. 说明

    file 对象使用 open 函数来创建

4、读取文件有以下几种方式:

4.1、read
  1. 说明

     读取指定长度的文件     

  2. 方法

    1
    f.read([size]) 
  3. 参数说明

    size: 读取的长度,以byte为单位,未给定或为负则读取所有

  4. 返回值

    返回从字符串中读取的字节。

  5. 举个栗子

    1
    2
    3
    4
    5
    6
    7
    8
    9
    # 相对路径
    with open('test.txt', 'r') as f:
    data = f.read()
    print(data)
    # 绝对路径
    with open('/Users/zhangwei/work/test.txt', 'r') as f:
    data = f.read()
    print(data)

4.2、readline
  1. 说明

    从文本中读取一行文本,该函数返回一行的文本字符串,包括换行符“\n”。第一次使用返回文件的第一行文本,第二次返回第二行文本,依此类推。 使用循环可遍历文件中的每一行文本 

  2. 方法

    1
    line = f.readline([size])
  3. 参数说明

    size: 读取的长度,以byte为单位,默认读取一行

  4. 举个栗子

    1
    2
    3
    with open('test.txt', 'r', encoding='utf-8') as f:
    data = f.readline()
    print(data)
4.3、把文件每一行作为一个list的一个成员
  1. 说明

    它的内部是通过循环调用readline()来实现的。如果提供size参数,size是表示读取内容的总长,也就是说可能只读到文件的一部分。

  2. 方法

    1
    list = f.readlines([sizeint])
  3. 参数说明

    size的限制读取大小, 就是说读出来的东西的大小不能超过那个值

  4. 返回值

    返回列表,包含所有的行

  5. 举个栗子

    1
    2
    3
    with open('test.txt', 'r', encoding='utf-8') as f:
    data = f.readlines(2)
    print(data)

4.4、总结

  1. 按字节读取,使用 read(size)
  2. 按行读取,使用 readline()
  3. 按行读取返回列表,使用 readlines()

5、写文件(write)

1、概述

写文件和读文件是一样的,唯一区别是调用open()函数时,传入标识符'w'或者'wb'表示写文本文件或写二进制文件

1
2
3
f = open('test.txt', 'w') # 若是'wb'就表示写二进制文件
f.write('Hello, world!')
f.close()

2、写文件有两种方式

2.1、write
  1. 说明

    把str写到文件中,不会换行

  2. 方法

    1
    write(str)
  3. 参数说明

    • 要写入的字符串
  4. 返回值

    写入的字符的个数.

  5. 举个栗子

    1
    2
    3
    with open('test.txt', 'w', encoding='utf-8') as f:
    count = f.write('ab')
    print(count)

    注意

    • w+, 文件不存在会自动创建文件, 并写入
    • a+, 追加的方式写入文件
1
2
3
4
#如果是写入的其他类型的数据, 则写之前需要手动转换 根据你打开文件的模式, 来决定到底是转成字符串还是转成字节对象
with open("new.txt", "w+t", encoding="utf-8") as file:
text = ("python", "hello", "world", 30)
file.write(str(text))
2.2、 writelines
  1. 说明

    把多个字符串写到文件中,写入的时候不会自动帮你格式化, 会把每个字符串元素挨个写在一起, 你应该在写入之前自行处理好格式

  2. 方法

    1
    f.writelines(str)
  3. 参数

    字符串

  4. 返回值

  5. 举个栗子

    1
    2
    3
    with open("new.txt", "a+", encoding="utf-8") as file:
    li = ["a", "b", "你好"]
    file.writelines(str(li))

三、file对象其它方法

1、close

  1. 说明

    关闭文件 python2.6 以后有一个with语句. 可以自动关闭文件.不用手动关闭

  2. 方法

    1
    f.close()
  3. 参数

  4. 返回值

2、flush

  1. 说明

    write到file的内部,在进程没有结束之前, 都是保存在内存中, 通过flush方法可以将文件刷到硬盘上

  2. 方法

    1
    f.flush()
  3. 举个栗子

    1
    2
    3
    4
    with open("new.txt", "a+", encoding="utf-8") as file:
    li = ["a", "b", "你好"]
    file.writelines(str(li))
    file.flush()

2、文件指针(了解)

  1. 说明

    文件指针 标记从哪个位置开始读取数据 第一次打开文件时,通常文件指针会指向文件的开始位置,当执行了read方法后,文件指针会移动到读取内容的末尾

3、tell

  1. 说明

    返回文件操作标记的当前位置,以文件的开头为原点

  2. 方法

    1
    int = f.tell()
  3. 参数

  4. 返回值

    文件操作的位置

  5. 举个栗子

    1
    2
    3
    4
    5
    6
    7
    #获取指针位置
    with open('test.txt','r+',encoding='utf-8') as f:
    data = f.read(8) #先读取8个字符
    print("当前指针位置:%s"%f.tell()) #查看当前指针位置
    print(data)
    f.seek(0) #重置指定到启始位
    print("当前指针位置:%s"%f.tell()) #在查看指针位置

4、seek

  1. 说明

    将文件打操作标记移到offset的位置

  2. 方法

    1
    f.seek(offset[,whence]) 
  3. 参数说明

    这个offset一般是相对于文件的开头来计算的,一般为正数。但如果提供了whence参数就不一定了,

    whence可以为0表示从头开始计算,

    1 表示以当前位置为原点计算。

    2 表示以文件末尾为原点进行计算。

    需要注意,如果文件以a或a+的模式打开,每次进行写操作时,文件操作标记会自动返回到文件末尾。

  4. 返回值

  5. 举个栗子

    1
    2
    3
    4
    5
    6
    7
    #获取指针位置
    with open('test.txt','r+',encoding='utf-8') as f:
    data = f.read(8) #先读取8个字符
    print("当前指针位置:%s"%f.tell()) #查看当前指针位置
    print(data)
    f.seek(0) #重置指定到启始位
    print("当前指针位置:%s"%f.tell()) #在查看指针位置

5、truncate

  1. 说明

    截断文件数据,仅保留指定之前数据(指定字节数)

  2. 方法

    1
    f.truncate(size) 
  3. 参数

    字节数

  4. 返回值

  5. 举个栗子

    1
    2
    3
    4
    with f = open('test.txt','r+',encoding='utf-8') as f:
    f.truncate(8) #文件只保留前8个字节数据,文件后面数据的全部删除
    re = f.read()
    print(re)

四、file对象字段

1、概要

文件对象除了方法之外,还有一些数据属性,这些属性保存了文件对象相关的附加数据。

文件对象属性 操作
file.close 表示文件已经被关闭,否则为False
file.encoding 表示文件所使用的编码
file.mode 表示文件打开时的访问模式
file.name 表示文件已经被关闭,否则为False
file.newlines 表示文件所采用的分隔符
file.softspace 为0表示在输出一数据后,要再加上一个空格符,为1表示不加,这个属性一般用不到

2、fileno

  1. 说明

    方法返回一个整型的文件描述符

  2. 举个栗子

    1
    2
    fno = file.fileno()
    print("文件描述符为: ", fno)

3、mode

  1. 说明

    获取文件打开时的访问模式

  2. 举个栗子

    1
    2
    f_mode = f.mode
    print(f_mode)

4、encoding

  1. 说明

    获取文件所使用的编码

  2. 举个栗子

    1
    print(f.encoding)

5、closed

  1. 说明

    文件是否关闭 True 表示关闭

  2. 举个栗子

    1
    print(f.closed)

五、其它

1、操作模式总结

模式 可做操作 若文件不存在 是否覆盖
r 只能读 报错 -
r+ 可读可写 报错
w 只能写 创建
w+ 可读可写 创建
a 只能写 创建 否,追加写
a+ 可读可写 创建 否,追加写

2、文件打开模式 w+ r+ a+ 区别

  1. w+ 打开文件并读写:

    1. 文件存在,则清空(也即写入空);

    2. 文件不存在,则创建文件 ;

    3. 文件流定位到开始位置, 所以read() 会得到空。

  2. r+ 打开文件并读写:

    1. 文件存在,打开文件,文件指针定位到文件开始位置;

    2. 文件不存在, 则报错文件不存在。

  3. a+ 打开文件并读写:

    1. 文件存在,打开文件,文件指针定位到文件开始位置,但不清空;

    2. 文件不存在,创建文件;

    3. 打开后读取时,在文件开头位置,

    4. 写入时,添加到文章末尾,并且指针位于添加后的末尾,所以再次读取会乱码。

    5. w 打开文件写入,也会清空文件,如果使用read(),则报错;a 打开文件添加,数据流添加到文件末尾,而不是w模式的清空后,添加到文件末尾。

    6. b可以附加到上述的字母后,形成rb, rb+, wb等等模式,针对二进制文件,比如exe, elf, jpeg格式的文件,进行文件操作; 在unix 类型的系统上,text格式与二进制的处理相同,但是非unix类型的系统上,换行格式不同,所以需要用加b模式来在指定是否是二进制