什么是文件
文件就是以硬盘为载体存储信息的集合
代码操作文件的基本流程
- 打开文件、创建文件
- 编辑文件内容
- 保存文件内容
- 关闭文件
基本语法结构
语法
# 完整语法格式
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
补充:
- 只能操作文本文件
- 必须要指定
encoding
参数 - 读写都是以字符串为最小单位
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
补充:
- 可以操作任意类型的文件
- 不需要指定
encoding
参数 - 读写都是以
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') # 重命名文件
- 优点:不会占用过多的内存
- 缺点:在文件修改过程中同一份数据存了两份