文章目录
- 一、文件的打开模式
- (一)控制文件读写操作的模式
- 1.模式r:只读(默认的模式)
- (1)特点:
- 2.模式w:只写
- (1)特点:
- 3.模式a:之追加写
- (1)特点:
- 4.总结:w与a的异同
- (1)相同点:
- (2)不同点:
- 5.案例示范:
- (二)控制文件内读写内容的模式
- 1.模式t:文本模式(默认)
- (1)特点:
- 2.模式b:bytes模式
- (1)特点:
- 3.上下文管理with
- 4.补充:+模式,可读可写
- (1)rt与r+t比较:
- (2)wt与w+t比较:
- (3)at与a+t比较:
- 二、文件操作的其他方法
- (一)读相关的方法
- (二)写相关的方法
- (三)其他方法
- 三、控制文件内指针移动
- (一)控制文件指针移动的单位
- 1.控制文件指针移动的单位都是字节;
- 2.例外情况:t模式下的read(n),代表的是n个字符,此外代表的全都是字节。
- 3.f.seek(offset,whence)
- (二)控制文件指针移动的三种模式
- 1.模式0:
- 2.模式1:
- 3.模式2:
- (三)使用案例:模拟程序记录日志的功能
一、文件的打开模式
(一)控制文件读写操作的模式
1.模式r:只读(默认的模式)
(1)特点:
文件不存在时报错,文件存在时文件指针跳到文件开头。
2.模式w:只写
(1)特点:
文件不存在时创建空文件,文件存在时清空文件,并且文件指针跳到文件开头。
3.模式a:之追加写
(1)特点:
文件不存在时创建空文件,文件存在时文件指针跳到文件末尾。
4.总结:w与a的异同
(1)相同点:
在打开文件不关闭的情况下,连续的写入,新的内容永远跟在老的内容之后。
(2)不同点:
重新打开文件,w模式会清空老的内容,而a模式会保留老的内容,并且指针跳到文件末尾。
5.案例示范:
# 示范一:注册功能
name = input('your name :').strip()
# 做合法性校验
# 1.如果输入的用户名包含特殊字符 让用户重新输入
# 2.如果输入的用户名已经存在也重新输入
pwd = input('your password :').strip()
# 做合法性校验:
# 1.密码的长度
# 2.如果密码包含特殊字符则重新输入
f_txt = open('user.txt',mode='at',encoding='utf-8')
f_txt.write('%s:%s\n' %(name,pwd))
f_txt.close()
# 示范2:登录功能
inp_name = input("your name: ").strip()
inp_pwd = input("your pwd: ").strip()
f_txt = open('user.txt',mode='rt',encoding='utf-8')
for line in f_txt:
user,pwd=line.strip('\n').split(':')
if inp_name == user and inp_pwd == pwd:
print('login successful')
break
else:
print('user or password error')
f_txt.close()
(二)控制文件内读写内容的模式
1.模式t:文本模式(默认)
(1)特点:
读写都是以str字符串为单位,一定要指定encoding参数。
# a.txt 'hello嘿嘿嘿哈哈哈'
f_txt = open('a.txt', mode='rt', encoding='utf-8')
res = f_txt.read()
print(res) # hello嘿嘿嘿哈哈哈
f_txt.close()
2.模式b:bytes模式
(1)特点:
读写都是以bytes为单位,一定不能指定encoding参数。
# a.txt 'hello嘿嘿嘿哈哈哈'
f_txt = open('a.txt', mode='rb')
data = f_txt.read()
# print(data, type(data)) # b'hello\xe5\x98\xbf\xe5\x98\xbf\xe5\x98\xbf\xe5\x93\x88\xe5\x93\x88\xe5\x93\x88' <class 'bytes'>
print(data.decode('utf-8')) # hello嘿嘿嘿哈哈哈
f_txt.close()
f_txt = open('a.txt', mode='wb')
f_txt.write("张三&罗翔".encode('utf-8')) # '张三&罗翔'覆盖原内容
f_txt.close()
3.上下文管理with
借助上下文管理,可以帮助我们不用专门去关闭文件,python解释器自动帮助我们关闭打开的文件,释放系统资源。
with open() as f_txt, open() as f1:
f_txt.read()
4.补充:+模式,可读可写
t、b模式必须与r、w、a模式联用。
+模式必须与r、w、a模式联用:r+、w+、a+
(1)rt与r+t比较:
1) rt:只读文本模式(默认的模式,如果不指定模式,就会默认此模式)
# a.txt 'hello嘿嘿嘿哈哈哈'
with open('a.txt', mode='rt', encoding='utf-8') as f_txt:
res = f_txt.tell()
res1 = f_txt.read()
res2 = f_txt.tell()
print(res, res1, res2) # 0 hello嘿嘿嘿哈哈哈 23
2) r+t:可读可写文本模式,开头就写类似wt模式,对原内容进行覆盖,可能会造成乱码。在读完内容之后,文件指针移动到末尾,写入内容之后,如三个汉字,会返回3个字符的长度,此时文件指针仍在末尾,无法读取出有效内容,文件指针在写入三个汉字后,文件指针移动9个字节。
# a.txt 'hello嘿嘿嘿哈哈哈'
with open('a.txt', mode='r+t', encoding='utf-8') as f_txt:
res = f_txt.tell()
# res0 = f_txt.write('嚯嚯嚯') # 必须读完再写,否则会覆盖原来的内容,造成乱码
res1 = f_txt.read()
res2 = f_txt.tell()
res3 = f_txt.write('嚯嚯嚯')
res4 = f_txt.read()
res5 = f_txt.tell()
print(res, res1, res2, res3, res4, res5) # 0 hello嘿嘿嘿哈哈哈 23 3 32
(2)wt与w+t比较:
1) wt:只写文本模式,不可读,报错后文件清空,也没有执行写的操作
# a.txt 'hello嘿嘿嘿哈哈哈'
with open('a.txt', mode='wt', encoding='utf-8') as f_txt:
res = f_txt.tell()
# res0 = f_txt.read() # io.UnsupportedOperation: not readable
res1 = f_txt.write('hello哈哈哈')
res2 = f_txt.tell()
print(res, res1, res2) # 0 8 14
#开始指针位置,写入字符个数,写入之后指针位置
2) w+t:可读可写文本模式,但是无论文件指针在何处,都无法读取出内容
# a.txt 'hello嘿嘿嘿哈哈哈'
with open('a.txt', mode='w+t', encoding='utf-8') as f_txt:
res = f_txt.tell()
res0 = f_txt.read()
res1 = f_txt.write('hello哈哈哈')
res2 = f_txt.read()
res3 = f_txt.tell()
print(res, res0, res1, res2, res3) # 0 8 14
(3)at与a+t比较:
1) at:只追加写文本模式
# a.txt 'hello嘿嘿嘿哈哈哈'
with open('a.txt', mode='at', encoding='utf-8') as f_txt:
res = f_txt.tell()
# res0 = f_txt.read() # io.UnsupportedOperation: not readable
res1 = f_txt.write('hello哈哈哈')
res2 = f_txt.tell()
print(res, res1, res2) # 23 8 37
# 最新文件内容:hello嘿嘿嘿哈哈哈hello哈哈哈
2) a+t:可读可写文本模式,写只追加
# a.txt 'hello嘿嘿嘿哈哈哈'
with open('a.txt', mode='a+t', encoding='utf-8') as f_txt:
res = f_txt.tell()
f_txt.seek(0, 0)
res0 = f_txt.read()
f_txt.seek(0, 0)
res1 = f_txt.write('hello哈哈哈')
res2 = f_txt.tell()
print(res, res0, res1, res2) # 23 hello嘿嘿嘿哈哈哈 8 37
# 最新文件内容:hello嘿嘿嘿哈哈哈hello哈哈哈
二、文件操作的其他方法
(一)读相关的方法
1) f.read() # 读取所有内容,执行完该操作后,文件指针会移动到文件末尾。
# read(n)注意:在t模式下,括号内的参数n值得是字符数,b模式下指的是字节数!
2) f.readline() # 从当前指针位置开始读取一行内容,光标移动到第二行首部
3) f.readlines() # 读取每一行内容,存放于列表中
# 强调:
# f.read()与f.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)
4) f.readable() # 判断文件是否可读
(二)写相关的方法
1) f.write('1111\n222\n') # 针对文本模式的写,需要自己写换行符
f.write('1111\n222\n'.encode('utf-8')) # 针对b模式的写,需要自己写换行符
2) f.writelines(['333\n','444\n']) # 文件模式
f.writelines([bytes('333\n',encoding='utf-8'),'444\n'.encode('utf-8')]) #b模式
3) f.writable() # 文件是否可读
4) f.flush() # 立刻将文件内容从内存刷到硬盘
(三)其他方法
1) f.closed # 文件是否关闭
2) f.encoding # 获取文件的编码格式,如果文件打开模式为b,则没有该属性
3) f.name # 获取文件名
4) f.truncate(n) # 从文件开头往后数n个字节保留下来,其余全部删除
# 如果n不指定,则从文件开头往后数指针当前所在的位置,其余全部删除
三、控制文件内指针移动
(一)控制文件指针移动的单位
1.控制文件指针移动的单位都是字节;
2.例外情况:t模式下的read(n),代表的是n个字符,此外代表的全都是字节。
with open('f.txt', mode='rt', encoding='utf-8') as f:
data = f.read(6) # 6个字符
print(data)
with open('f.txt', mode='rb') as f:
# data=f.read(6) # 6个字节
data = f.read(8) # 8个字节
print(data.decode('utf-8'))
3.f.seek(offset,whence)
f.seek(n,模式) # n代表的移动的字节个数
(二)控制文件指针移动的三种模式
1.模式0:
参照文件的开头开始移动(只有0模式可以在t模式下使用,1、2模式只能在b模式下使用)
# a.txt用utf-8编码,内容如下(abc各占1个字节,中文“你好”各占3个字节)
abc你好
# 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')) #输出结果为: 好
2.模式1:
参照指针当前所在的位置(只能在b模式下使用)
# 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
3.模式2:
参照文件末尾的位置(只能在b模式下使用)
# 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
for i in range(10000):
with open('access.log', mode='at', encoding='utf-8') as f:
t = time.strftime('%Y-%m-%d %H:%M:%S')
content = '张三给李四转了%s毛钱' %i
msg = f'{t} {content}\n'
f.write(msg)
time.sleep(3)
# 监控日志
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.3)
else:
print(line.decode('utf-8'), end='')
%H:%M:%S')
content = '张三给李四转了%s毛钱' %i
msg = f'{t} {content}\n'
f.write(msg)
time.sleep(3)
# 监控日志
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.3)
else:
print(line.decode('utf-8'), end='')