什么是文件

文件就是以硬盘为载体存储信息的集合

代码操作文件的基本流程

  1. 打开文件、创建文件
  2. 编辑文件内容
  3. 保存文件内容
  4. 关闭文件

基本语法结构

语法

# 完整语法格式
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)

参数

  • file: 必需,文件路径(相对或者绝对路径)。
  • mode: 可选,文件打开模式
  • buffering: 设置缓冲
  • encoding: 一般使用utf8
  • errors: 报错级别
  • newline: 区分换行符
  • closefd: 传入的file参数类型
  • opener: 设置自定义开启器,开启器的返回值必须是一个打开的文件描述符

mode参数:

访问模式描述
r (read)只读模式,不能写(文件必须存在,不存在会报错)
w (write)只写模式,不能读(文件存在则会被覆盖内容(要千万注意),文件不存在则创建)
a (append)追加模式,不能读,文件不存在在则创建
r+读写模式
w+写读模式
a+追加读模式
rb二进制读模式
wb二进制写模式
ab二进制追加模式
rb+二进制读写模式
wb+二进制写读模式
ab+二进制追加读模式

结构1(了解即可)

f = open()
f = close()

使用

open(r'a.txt')  # 相对路径,以后写路径为了防止特殊符号 前面直接加r
open(r'/Users/kevin/Desktop/a.txt')  # 绝对路径

# open(文件的路径,文件的操作模式,文件的编码)
res = open(r'a.txt', 'r', encoding='utf8')
print (res.read()). # 读取文件内容
res.close()  # 关闭文件

结构2(推荐使用)

# 1. 在执行完子代码块后,with 会自动执行f.close(),f为变量名
with open() as f:
    pass  # 补全语法结构 本身没有任何功能

# 2、可用用with同时打开多个文件,用逗号分隔开即可
with open() as f,open() as f:  
    pass 

使用

with open('a.txt','r') as read_f,open('b.txt','w') as write_f:  
    data = f.read()
print(data)

文件的操作模式

r 模式

只读模式,只能读不能写

使用

with open(r'a.txt', 'r', encoding='utf8') as f:
    print(f.read())
    # 今天你努力了吗?

补充:路径不存在会直接报错!

w模式

只写模式,只能写不能读

使用

with open(r'a.txt', 'w', encoding='utf8') as f:
    f.write('今天你写代码了吗?')

with open(r'b.txt', 'w', encoding='utf8') as f1:
# 换行最早的时候:\r\n,为了节省空间支持一个字符,根据操作系统的不同可能有所区别
    f1.write('hhhh\n')
    f1.write('hhhh\n')
    f1.write('hhhh\n')

补充:路径不存在:自动创建文件,路径存在,先清空文件内容 之后再写入数据

a模式

只追加模式,在文件末尾添加内容

使用

with open(r'a.txt', 'a', encoding='utf8') as f:
    f.write('hhhh')
  

补充:路径不存在,自动创建文件,路径存在,不会清空文件内容而是在文件末尾等待新内容的添加

t模式

文本模式,是默认的模式

使用

with open(r'a.txt', 'rt', encoding='utf8') as f:
    pass
with open(r'a.txt', 'rw', encoding='utf8') as f:
    pass
with open(r'a.txt', 'ra', encoding='utf8') as f:
    pass

补充:

  1. 只能操作文本文件
  2. 必须要指定encoding参数
  3. 读写都是以字符串为最小单位

b模式

二进制模式 ,可以操作任意类型的文件

使用

with open(r'a.txt', 'rb') as f:
    pass
with open(r'a.txt', 'rb') as f:
    pass
with open(r'a.txt', 'rb') as f:
    pass

补充:

  1. 可以操作任意类型的文件
  2. 不需要指定encoding参数
  3. 读写都是以bytes类型为最小单位

文件内置方法

file.close()  # 关闭文件
file.write(str)  # 写入文件内容(字符串或者bytes类型)
file.writelines(sequence) # 可以将列表多个元素写入文件
file.writable()  # 判断文件是否可写
file.read([size])  # 一次性读取文件内容,光标会移动到文件末尾
file.readline([size])  # 一次只读一行内容,用for可以代替
file.readlines([size])  #  结果是一个列表 里面的各个元素是文件的一行行内容
file.readable()  # 判断当前文件是否可读
file.seek(offset[sizeint])  # 移动文件读取指针到指定位置
file.tell()  # 获取光标基于文件开头的字节数
file.flush()  # 相当于主动按了ctrl+s(保存)  
file.isatty()  # 文件连接到一个终端设备返回 True or False
file.next() # Python 3 不支持 next() 方法,返回文件下一行

文件光标移动

with open (r'a.txt', 'r', encoding='utf8') as f:
    print(f.read(3))   # read在文本模式下,括号内的数字表示的是读取指定的字符个数
    # 今天你
with open (r'a.txt', 'rb') as f:
    print(f.read(3))  # read在二进制模式下,括号内的数字表示的是读取指定的字节数
    # b'\xe4\xbb\x8a'
    print(f.read(3).decode('utf8'))
    # 天
    unicode所有的字符都是用2bytes来起步表示

控制光标的移动

因为文件内指针的移动都是由读/写操作而被动触发的,若想读取文件中某一个特定位置的数据,则需要用file.seek方法主动控制文件内指针的移动

语法

fileObject.seek(offset, whence)
# offset -- 开始的偏移量,也就是代表需要移动偏移的字节数,如果是负数表示从倒数第几位开始
# whence -- 可选,默认值为 0。给 offset 定义一个参数,表示要从哪个位置开始偏移;
#           0 表示从文件开头开始算起 (支持文本模式和二进制模式)
#.          1 表示从当前位置开始算起 (只支持二进制模式)
#           2 表示从文件末尾算起 (只支持二进制模式)

# 如果操作成功,则返回新的文件位置,如果操作失败,则函数返回 -1

使用

注:这里我a文本的是“今天你写代码了吗”,一共25个字节

参数whence是0

with open(r'a.txt', 'rb') as f:
    print(f.read(3).decode('utf8'))
    # 今
    print(f.seek(1))  # 从文件头开始,所以返回位置1
    # 1

参数whence是1

with open(r'a.txt', 'rb') as f:
    print(f.read(3).decode('utf8'))
    # 今
    print(f.seek(1, 1))  # '今'字占三个字节,参数1为当前位置,所以返回位置4
    # 4

参数whence是2

with open(r'a.txt', 'rb') as f:
    print(f.seek(1, 2))  # 从文尾开始,往前移动一个字节
    # 25
with open(r'a.txt', 'rb') as f:
    print(f.seek(-1, 2))  # 从文尾开始,往前移动一个字节
    # 23

文件修改

了解

with open(r'a.txt', 'r+t', encoding='utf8') as f:
    f.seek(9)  # 默认是0模式,从文件开头开始
    f.write('去')  # 因为光标读了九个字节,然后写入‘去’(3个字节),所以把‘写’覆盖掉了    
    # 今天你去代码了吗

补充:文件数据硬盘的内容只能“覆盖”,不能“删除”

思路一

将文件内容发一次性全部读取到内存中,然后在内存中修改完毕后再覆盖写回原文件

with open('a.txt', mode='r', encoding='utf-8') as f:
    data = f.read()
with open('a.txt', mode='w', encoding='utf-8') as f:
    f.write(data.replace('去', '写'))
  • 优点:在文件修改过程,只有一份数据
  • 缺点:如果文件数据大,会过占用过多的内存空间

思路二

以读的方式打开原文件,以写的方式打开一个临时文件,一行行读取原文件内容,修改完后写入临时文件

import os  # 模块
with open('a.txt', 'r', encoding='utf-8') as read_f, \
        open('a.txt.swap', 'w', encoding='utf-8') as wrife_f:
    for line in read_f:
        wrife_f.write(line.replace('写', '敲'))
os.remove('a.txt')  # 删除文件
os.rename('a.txt.swap', 'a.txt')  # 重命名文件
  • 优点:不会占用过多的内存
  • 缺点:在文件修改过程中同一份数据存了两份
Last modification:March 15, 2022
如果觉得我的文章对你有用,请随意赞赏