一、文件操作模式补充
除了r、w、a三种纯净模式外,还有r+、w+、a+三种模式,分别叫做读写、写读、追加写读
# mode='r+' with open(r'test',mode='r+',encoding='utf-8') as f: print(f.readable()) # True print(f.writable()) # True # mode='w+' with open(r'test',mode='w+',encoding='utf-8') as f: print(f.readable()) # True print(f.writable()) # True # mode='a+' with open(r'test',mode='a+') as f: print(f.readable()) # True print(f.writable()) # True
二、文件内的光标操作
在将光标之前先了解read()函数中的参数,在rt模式下read内的数字表示的是字符的个数除此之外,数字标识的都是读取的字节数。

你追到我
我就让你嘿嘿嘿
# 在rt模式下 read内的数字 表示的是字符的个数 # 初次之外,数字表示的都是字节
# 一个中文需要三个字节
with open(r'test','r',encoding='utf-8') as f: print(f.read(5)) # 你追到我 with open(r'test','rb') as f: res1 = f.read(9) # 读的是九个字节bytes print(res1) # b'xe4xbdxa0xe8xbfxbdxe5x88xb0' print(str(res1, encoding="utf-8")) # 你追到 with open(r'test','rb') as f: res2 = f.read(8) # 读的是八个字节bytes print(res2) # b'xe4xbdxa0xe8xbfxbdxe5x88' print(str(res2, encoding="utf-8")) # 报错:UnicodeDecodeError: 'utf-8' codec can't decode bytes in position 6-7: unexpected end of data
文件内的光标的作用就是控制read()从哪开始读
光标的函数为seek(offset, whence)。offset指的是相对偏移量,即光标移动的位数;whence可以为0、1、2,0表示参照文件的开头,t和b都可以使用,1表示光标所在的当前位置,只能在b模式下使用,2表示参照文件的末尾,只能在b模式下使用。

你追到我
我就让你嘿嘿嘿

# whence = 0,rt模式下 with open(r'test','rt',encoding='utf-8') as f: print(f.read(1)) # 你 # f.seek(6,0) # seek移动都是字节数 # f.seek(4,0) # seek移动都是字节数 # print(f.read(1)) f.seek(0,0) print(f.read(1)) # 你 f.seek(0, 0) print(f.read(1)) # 你 f.seek(6,0) print(f.read()) # 到我 我就让你嘿嘿嘿 # whence = 0,rb模式下 with open(r'test','rb') as f: print(f.read(3).decode('utf-8')) # 你 f.seek(0,0) print(f.read(3).decode('utf-8')) # 你 f.seek(6,0) print(f.read(3).decode('utf-8')) # 到 # whence = 1,rb模式下 with open(r'test','rb') as f: print(f.read(3).decode('utf-8')) # 你 f.seek(3,1) print(f.read(3).decode("utf-8")) # 到 # whence = 2,rb模式下 with open(r'test','rb') as f: print(f.read()) # b'xe4xbdxa0xe8xbfxbdxe5x88xb0xe6x88x91 xe6x88x91xe5xb0xb1xe8xaexa9xe4xbdxa0xe5x98xbfxe5x98xbfxe5x98xbf' f.seek(-12,2) print(f.read()) # b'xe4xbdxa0xe5x98xbfxe5x98xbfxe5x98xbf' f.seek(-12, 2) print(f.read().decode('utf-8')) # 你嘿嘿嘿
三、监测文件
基于文件的读写操作和光标的操作,可以写一个监测文件写入的程序,用来记录文件内容的添加记录。

2019-07-08 11:16:13 egon给jason发了1个亿的工资 2019-07-08 11:16:14 egon给jason发了1个亿的工资 2019-07-08 11:27:48 egon给jason发了1个亿的工资 2019-07-08 11:29:42 egon给jason发了1个亿的工资 2019-07-08 11:30:32 egon给jason发了1个亿的工资 2019-07-08 11:30:37 egon给jason发了1个亿的工资 2019-07-08 11:33:25 egon给jason发了1个亿的工资 2019-07-08 11:33:33 egon给jason发了1个亿的工资 2019-07-08 16:07:35 egon给jason发了1个亿的工资

import time a = time.strftime("%Y-%m-%d %x") with open(r"test01.text", mode="a", encoding="utf-8") as f: f.writer("%segon给我发了1亿工资“% a) # 2019-07-08 16:07:35 egon给jason发了1个亿的工资

# 文件监测 with open(r"test01.txt", mode="r",encoding="utf-8") as f: f.seek(0,2) # 将文件光标移动到文件的末尾 while True: # 从文件的末尾循环读取文件末尾可能出现的数据 a = f.readline() # 读取可能被写入文件末尾的数据 if a: # 判断是否有数据写入 print(a) # 打印写入的数据
四、截断文件
所谓的截断文件就是保留自己需要的内容,其余内容被删除

with open(r'test','a',encoding='utf-8') as f: f.truncate(6) # 接收的字节的长度 整型 # 保留0~6字节数 后面的全部删除(截断)
保留了test文件的前六个字节后的结果(右图)
五、修改文件
文件的存储有个特点,当一个文件存好后,若想向文件中插入字符间插入其它字符时,是不可行的,只能添加在文件的末尾。想要修改文件中的字符时,可以使用新字符替换掉原来的字符,或者将文件中的内容以字符串的形式读取出来,修改完成后存入另一个文件中,删除源文件,将新文件的名字改成源文件的名字。

# 修改文件 # 先将数据由硬盘读到内存(读文件) # 在内存中完成修改(字符串的替换) # 再覆盖原来的内容(写文件) with open(r'test02.txt','r',encoding='utf-8') as f: data = f.read() print(data) print(type(data)) with open(r'test02.txt','w',encoding='utf-8') as f: res = data.replace('egon','jason') print(data) f.write(res)

# 文件修改方式2 # 创建一个新文件 # 循环读取老文件内容到内存进行修改 将修改好的内容写到新文件中 # 将老文件删除 将新文件的名字改成老文件名 import os with open(r'test02.txt','r',encoding='utf-8') as read_f, open(r'test02.swap','a',encoding='utf-8') as write_f: for line in read_f: new_line = line.replace('jason','egon') write_f.write(new_line) os.remove('test02.txt') os.rename('test02.swap','test02.txt')
两种方法的优缺点:
对于方法一:
优点:任意时间硬盘上只有一个文件 不会占用过多硬盘空间
缺点:当文件过大的情况下,可能会造成内存溢出
对于方法二:
优点:内存中始终只有一行内容 不占内存
缺点:再某一时刻硬盘上会同时存在两个文件