打开文件
函数 open()
参数说明:
file: 文件路径
mode: 文件的读写方式, 默认 r, 只读方式;
buffering: 设置缓冲策略, 0 用于二进制文件, 1 为行缓冲, 用于文本模式; 默认二进制文件固定大小缓冲, 文本文件行缓冲
encoding: 设置编码, 默认 utf-8; 该参数不能用于二进制模式;
errors: 设置怎么处理文件的编码异常, 默认 strict, 发生错误抛出异常; 设置 ignore 忽略编码异常, 可能导致数据丢失, 这个参数不能用于二进制模式;
newline: 设置换行符, 默认换行符为'\n','\r','\r\n', 写入文件的时候, 所有文本中的上述三种都会转换成'\n'换行符; 当设置为''时, 也启用默认模式; 如果设置其它合法值, 则使用其他值, 一般不用;
closefd=True : 设置文件描述符的状态, 当为 False 时, 文件关闭但描述符不关闭, 但是打开文件时指定了文件名, 那么设置 False 不会起作用
文件打开方式
r: 以只读方式打开文件文件的指针将会放在文件的开头这是默认模式
w: 打开一个文件只用于写入如果该文件已存在则将其覆盖如果该文件不存在, 创建新文件
a: 打开一个文件用于追加如果该文件已存在, 文件指针将会放在文件的结尾也就是说, 新的内容将会被写入到已有内容之后如果该文件不存在, 创建新文件进行写入
x: 创建一个新文件, 将其打开并编写; 如果文件已经存在报错;
rb: 以二进制格式打开一个文件用于只读文件指针将会放在文件的开头这是默认模式
wb: 以二进制格式打开一个文件只用于写入如果该文件已存在则将其覆盖如果该文件不存在, 创建新文件
ab: 以二进制格式打开一个文件用于追加如果该文件已存在, 文件指针将会放在文件的结尾也就是说, 新的内容将会被写入到已有内容之后如果该文件不存在, 创建新文件进行写入
r+: 打开一个文件用于读写文件指针将会放在文件的开头
w+: 打开一个文件用于读写如果该文件已存在则将其覆盖如果该文件不存在, 创建新文件
a+: 打开一个文件用于读写如果该文件已存在, 文件指针将会放在文件的结尾文件打开时会是追加模式如果该文件不存在, 创建新文件用于读写
rb+: 以二进制格式打开一个文件用于读写文件指针将会放在文件的开头
wb+: 以二进制格式打开一个文件用于读写如果该文件已存在则将其覆盖如果该文件不存在, 创建新文件
ab+: 以二进制格式打开一个文件用于追加如果该文件已存在, 文件指针将会放在文件的结尾如果该文件不存在, 创建新文件用于读写
关闭文件
- close()
- f = open(file)
- f.close()
注意:
由于文件每次打开都需要调用 Close 函数关闭, 可以使用上下文管理器管理文件, 其会自动在适当的时候关闭文件
- with open(filename) as f:
- f.read()
文件普通读写
读
方法一: read()
- with open(filename) as f:
- f.read() # 一次性读取全部, 在大文件这是不可取的
- f.read(5) # 读取 5 个字节, 如果使用 UTF-8 编码, 5 表示 5 个汉字, 也表示 5 个字母
- f.read(6) # 同一个 f 对象, 多次读取时在上一次的基础上继续往下, 如果超过则有多少读多少
方法二: readline()
- with open(filename) as f:
- f.readline() # 按行来读取, 每次返回一行,
- f.readline() # 多次读取在上一行的基础上往下, 换行符也会被读取
方法三: readlines()
- with open(filename) as f:
- t = f.readlines() # 按行读取全部的内容作为一个列表返回
readable() 方法可以用来判断文件是否可读
写
方法一: write()
- with open(filename,'w',encoding='utf-8') as f:
- t = f.write('ddd') # 将内容写入, 必须是字符串格式, 不可以是数字, 返回的是字符串的个数, 包括了换行符 \ r\n 占两个字符 (windows), 占一个字符 \ n(linux)
- t = f.write('aaa') # 多次写入在原来的基础上继续写入
方法二: writelines()
- with open(filename,'w',encoding='utf-8') as f:
- f.writelines(['aa','bb']) # 该方法自动将列表元素拼接起来写入文件, 参数时一个可迭代对象, 列表字典集合都可以
writeable() 可以判断打开的文件对象 f 究竟是可读的还是可写的
注意的问题
f.write(123) 这种是不被允许的, 必须转化成二进制或字符串;
open(filename,'rb',encoding='utf-8') : 以二进制格式打开文件是不能指定编码的, 否则报错
以二进制格式打开文件, 写入的必须是字节文件, 同时写入返回的是字节数; 以文本模式打开, 写入的必须是文本, 同时返回的是字符串个数; 一个汉字字符串占 3 个字节
普通字符串转化为字节文件的方法:
b'123adf': 这种方法只能针对数字和字母, 默认使用 ascii 编码, 不能转化汉字;
'123adf'.encode('utf-8): 可以转化字母和汉字;
bytes('我的',encoding='utf-8'): 可以转化字母和汉字, 但必须 指定编码格式;
文件的定位读写
tell(): 获取文件指针的位置
- with open(filename,'r',encoding='utf-8') as f:
- f.read(3)
- t = f.tell() # 获取指针的位置, 返回 3, 如果读取到换行符, 换行符在 windows 占两个字节
seek(offset,from): 设置指针的位置
参数
offset: 偏移量, 设置负数表示向前偏移, 正数表示向后偏移, 一个汉字占 3 个字节, 字母占一个字节
from: 偏移的方向
表示文件开头
表示当前位置
表示文件末尾
- with open(filename,'r',encoding='utf-8') as f:
- f.read(3)
- a = f.seek(0,0) # 返回指针定位后的实际位置, 默认偏移方向从文件开头算起
注意
在文本模式下打开文件, 偏移方向只能从文件开头算起, 参数 from 只能为 0, 这是因为文本模式涉及到编码的问题, 以二进制格式打开文件就可以设置不同的方向
每次打开文件, 读操作的指针都是在文件的开头, 写操作的指针在文件的末尾, 直到文件被关闭;
几个经典的案例
文件同时读写的情况
- with open('test.txt', 'r+') as f:
- print(f.tell()) # 当前指针的位置在开头 0
- a = f.read(3) # 指针到了位置 3
- print(a)
- print(f.tell())
- h = f.write('hhh') # 从文件的末尾写入, 相当于追加数据
- print(h)
- c = f.tell() # 指针在文件的末尾
- print(c)
- print(f.read()) # 读取从位置 3 到文件原来的末尾的数据
- print(f.tell()) # 当前位置在新的文件末尾和 c 相同
总结: r + 模式下, 如果同一个文件对象需要读和写, 读和写各有一个指针, 它们是相互独立的, 读写位置各不干扰; 但是 tell 函数获取到的位置优先表示写的位置; 即当程序执行时, 如果只有读, tell 获取的位置是读的位置; 如果出现了写, tell 获取的位置就一定是写的位置了, 无论后面还有没有更多的读操作; 同理其他的模式也一样;
文件同时读写存在偏移的情况
- with open('test.txt', 'r+') as f:
- print(f.tell()) # 当前读指针的位置在开头 0, 写指针还未初始化
- print(f.read(3)) # 读指针到了位置 3
- print(f.tell()) # 获取到读指针的位置为 3
- f.seek(0) # 指针偏移到文件的开头, 只能影响一个指针
- print(f.read(3)) # 读指针到了位置 3
- h = f.write('gggg') # 增加一个文件描述符, 写指针初始化到文件的末尾, 写入数据
- j = f.tell() # 获取写的位置优先, 写指针在文件末尾
- print(j)
- f.seek(0) # 指针偏移到文件的开头, 读文件的数据更新, 加入了写入的数据
- j = f.tell() # 获取写指针在文件的开头
- print(j)
- h = f.write('vvvv') # 从文件开头写入数据, 覆盖原来的数据
- c = f.tell() # 获取写指针在文件的位置 4
- print(c)
- print(f.read(4)) # 读取从位置 4 往后的 4 个字符
- print(f.tell()) # 读指针在文件 8 位置
- h = f.write('xxx') # 从文件的末尾写入, 相当于追加数据
- print(f.tell()) # 当前位置在新的文件末尾
- print(f.read()) # 从 8 位置读取所有的数据
总结:
seek() 函数只能影响它下面的第一次的读写操作; 并且会将上一次写入的数据更新到读缓冲区中;
在 r + 模式下, write() 总是从文件的末尾写入, 除非受 seek 函数的影响;
write() 操作被偏移影响后, 其后的 read 操作的指针会被移到 write 操作的位置;
文件同时读写存在且存在更新的情况
- with open('test.txt', 'r+') as f:
- f.read()
- f.seek(2,0) # 定位到到文件的开头往右 2 的位置
- f.truncate() # 将 2 位置后所有的数据删除
- f.write('aaa') # 写入新的数据
truncate(): 动态删除数据, 从当前指针删除后面所有的数据
其他方法
flush(): 刷新文件内部缓冲, 直接把内部缓冲区的数据立刻写入文件, 而不是被动的等待输出缓冲区写入, 一般 close() 函数时先调用 flush(), 然后再关闭文件描述符
fileno: 返回一个整型的文件描述符, 很少用到;
isatty(): 文件是否连接到一个终端的设备;
truncate(): 文件截取, 无参数时从当前的指针位置删除后面所有; 有参数时从首行首字母截取数据留下来, 其余的删除;
来源: https://www.cnblogs.com/cwp-bg/p/8531588.html