今日内容概要
文件操作
-
什么是文件
文件是操作系统提供给应用程序来操作硬盘的虚拟概念。
-
为何要用文件
读写文件就是在读写用硬盘,我们对文件的读写操作都会被操作系统转换成硬盘的操作 应用程序--------->>> 文件对象,文件句柄 操作系统--------->>> 文件 硬件------------->>> 硬盘
-
如何用文件
1.控制文件读写操作的模式 r(默认):只读 w:只写 a:只追加写 2.控制文件读写内容的模式 t(默认):读写都是以字符串为单位,只适用于文件,文件必须指定encoding参数 b:读写都是以Bytes为单位的,适用于所有文件,一定不能指定encoding
-
r模式
# r 只读模式:在文件不存在会报错,文件存在文件内指针直接跳到文件开头 with open ('a.txt', mode='rt',encoding='utf8' ) as f: res = f.read() #
-
w模式
# w 只写模式:在文件不存在会新建空文档,文件存在时会清空文件,文件指针跑到文件开头 with open('b.txt',mode='wt',encoding='utf8') as f: f.write('你好\n') f.write('我好\n') # 注意: w模式,在打开文件不关的情况下,联系写入,新写的内容永远跟在后面
-
a模式
# a 只追写模式,如果文件不存在则创建空文档,文件存在不会清空,文件指针处于文件末尾 with open('c.txt',mode='at',encoding='utf8') as f: f.write('4444') f.write('5555') f.write('6666')
-
操作文件的方法
# 读 .read() # 读取所有文件内容,执行完该操作后,文件指针会移动到文件末尾 .readline() # 读取一行内容,光标移动到第二行首 .readlines() # 读取每一行内容,存放于列表 #### 如果文件过大会导致内存溢出 # 方法一 with open('a.txt',mode='rt',encoding='utf-8') as f: for line in f: print(line) # 同一时刻只读入一行内容到内存中 # 方式二 with open('1.mp4',mode='rb') as f: while True: data=f.read(1024) # 同一时刻只读入1024个Bytes到内存中 if len(data) == 0: break print(data) # 写操作 f.write('1111\n222\n') # 针对文本模式的写,需要自己写换行符 f.write('1111\n222\n'.encode('utf-8')) # 针对b模式的写,需要自己写换行符 f.writelines(['333\n','444\n']) # 文件模式 f.writelines([bytes('333\n',encoding='utf-8'),'444\n'.encode('utf-8')]) #b模式
-
主动指定文件指针移动
# 大前提: 文件内指针的移动都是以Bytes为单位,唯一例外的是t模式下的read(n),n 是以字符为单位 with open('a.txt',mode='rt',encoding='utf8') as f: data = f.read(3) # 读取3个字符 with open('a.txt',mode='rb') as f: data = f.read(3) # 读取3个Bytes # 之前文件内指针的移动都是由读/写操作而被动触发的,若想读取文件某一特定位置的数据,则则需要用f.seek方法主动控制文件内指针的移动,详细用法如下: # f.seek(指针移动的字节数,模式控制): # 模式控制: # 0: 默认的模式,该模式代表指针移动的字节数是以文件开头为参照的 # 1: 该模式代表指针移动的字节数是以当前所在的位置为参照的 # 2: 该模式代表指针移动的字节数是以文件末尾的位置为参照的 # 强调:其中0模式可以在t或者b模式使用,而1跟2模式只能在b模式下用 # 0模式的使用 with open('a.txt',mode='rt',encoding='utf-8') as f: f.seek(3,0) # 参照文件开头移动了3个字节 print(f.tell()) # 查看当前文件指针距离文件开头的位置,输出结果为3 print(f.read()) # 从第3个字节的位置读到文件末尾,输出结果为:你好 # 注意:由于在t模式下,会将读取的内容自动解码,所以必须保证读取的内容是一个完整中文数据,否则解码失败 with open('a.txt',mode='rb') as f: f.seek(6,0) print(f.read().decode('utf-8')) #输出结果为: 好 # 1模式的使用 with open('a.txt',mode='rb') as f: f.seek(3,1) # 从当前位置往后移动3个字节,而此时的当前位置就是文件开头 print(f.tell()) # 输出结果为:3 f.seek(4,1) # 从当前位置往后移动4个字节,而此时的当前位置为3 print(f.tell()) # 输出结果为:7 # a.txt用utf-8编码,内容如下(abc各占1个字节,中文“你好”各占3个字节) abc你好 # 2模式的使用 with open('a.txt',mode='rb') as f: f.seek(0,2) # 参照文件末尾移动0个字节, 即直接跳到文件末尾 print(f.tell()) # 输出结果为:9 f.seek(-3,2) # 参照文件末尾往前移动了3个字节 print(f.read().decode('utf-8')) # 输出结果为:好 # 小练习:实现动态查看最新一条日志的效果 import time with open('access.log',mode='rb') as f: f.seek(0,2) while True: line=f.readline() if len(line) == 0: # 没有内容 time.sleep(0.5) else: print(line.decode('utf-8'),end='')