文件的三种模式:默认为r模式
操作模式,分为 r(read)、w(write)、a(append)
r模式:仅读取
r+ 写入的位置是 当前光标所在位置,会直接改写当前位置的值
r+ 可以续写么? 可以,但是必须把光标挪到最后
r 没有创建文件的能力
w模式:写入,且每次是新写入
# w+ 拥有写入权限,可以创建文件
# w 所有的write操作是先写在内存中,只有结束的时候才会执行进去
# w+ 和 r+ 的区别是 r+ 只在当前位置写入,w+ 是全部重写内容
a模式:追加模式
1、文件打开和读取
a、文件读写(i/o):打开文件(打开文件的时候,一定是要文件存在的)、读取内容、关闭文件。
file = open("a.txt", encoding="utf-8") # 同一个路径下,打开的文件是一个数据流
print(file) # 读取file的文件信息
print("文件全部读取:",file.read()) # 全部读取
print("readline:", file.readline()) # 逐行的读取
print("readlines:", file.readlines()) # 将数据转为一个list
for line in file.readlines(): #循环输出列表的内容
print("readlines:", line.strip())
file.close() #关闭文件
b、文件的遍历
open打开的文件,是一个流,
print("readline:::", file.readline())
print("readlines:::", file.readlines()) # 将数据转为一个list
第一种遍历文件的方式,全部读取并且转为list,数据都会存储到内存中,影响电脑的效率
for line in file.readlines():
print("line::", line.strip())
第二种遍历文件的方式,逐行读取进行操作,不会提前加载到内存中,可以解决性能问题
for line in file:
print("line::", line.strip())
c、找到文件的位置
file = open("n.txt", encoding="utf-8")
print(file.read())
print(file)
print("没读时", file.tell())
print(file.readline().strip())
# 当前所在位置
print("第一次读取", file.tell())
print(file.readline().strip())
print("第二次读取", file.tell())
# 跳转到目标位置
file.seek(19)
print(file.readline().strip())
file.close()
n.txt的数据内容
123
qwe1
asd
zxc
-----结果输出------------
没读时 0
123
第一次读取 4
qwe1
第二次读取 9
asd
2、文件写入和改写
file = open("a.txt", "w", encoding="utf-8")
file.write("天琴座\n") # 写入数据
file.write("天琴座\n")
l=['xiaobai','xiaoming','xiaohei']
for i in l:
file.write(i)
file.write('\n')
file.close()
3、文件的追加
file = open("a.txt", "a", encoding="utf-8")
file.write("天琴座\n") # 写入数据
file.close()
4、练习,日志监控
# nginx日志监控系统
# 用来监控nginx日志中记录的ip,当某一个ip出现次数超过50次以后,报警 xxxx 地址,已经访问超过50次
# 运行频率,每分钟运行一次
# 数据来源为: nginx的access.log 读取文件(I/O操作)
# 思路分析
# 1、读取文件(I/O操作) open(access.log)
# 2、解析文件,分析出ip
# 3、把ip存起来,并且记录ip出现次数
# 4、分析记录到每个ip出现次数,当某一个ip出现次数超过50次,打印出 这个ip出现次数超过50次了
# 5、让这个程序滚动起来,不会停止;
# 6、每次读取当时候需要跳过已读数据; 需要记录上次到哪了,下次读取到时候先进行跳转
import time
file = open("access.log", encoding="utf-8")
# 第一种方式通过list实现性能较差,每次要全文读取
iplist=[]
while True:
for line in file:
ip = line.split(' ')[0] # 转换为list
# print(ip)
iplist.append(ip)
# print(iplist)
ip_set=set(iplist)
# print(ip_set)
for ip in ip_set:
print(ip,":",iplist.count(ip))
if iplist.count(ip)>=50:
print(ip+"此IP已经超过50次,请关注风险")
file.tell()
print("=========结束一轮监测================")
time.sleep(5)
file.close()
import time
file = open("access.log", encoding="utf-8")
# 第二种方式,通过dict 和 file的游标来实现的方式,增量读取解决读取文件的性能问题
ip_dict = {}
point = 0
while True:
# 1、读取文件(I/O操作)
file = open("access.log", encoding="utf-8")
# 跳转到上一次记录到位置,如果是第一次则记录的位置是文件开始处
file.seek(point)
# 2、解析文件,分析出ip
for line in file:
# 从log中取出ip
ip = line.strip().split(" ")[0]
# 3、把ip存起来,存到一个字典,并且记录ip出现次数
# 存储的容器可以是list,可以是dict,需要考虑是否要清空
# 如果清空则每次全量读取
# 如果不清空则每次要加入增量,不然能把重复数据加入
# 这个地方就需要每次读取的时候跳到上次结束位置,所以不清空的模式需要用seek和tell
# 字典计数器的功能,每个key就是一个ip ,值是ip的出现次数
if ip_dict.get(ip): # 非空即真 如果字典中之前记录过该ip,则记录的次数+1
ip_dict[ip] += 1 # a += 1 等同于 a = a + 1
else: # 如果之前未记录,则初始化一个记录次数,初始化的值:1
ip_dict[ip] = 1
# 读取文件完成以后,记录一下这一次读取到哪里了,方便下一次seek到当前点
point = file.tell()
# 4、分析记录到每个ip出现次数,当某一个ip出现次数超过50次,打印出 这个ip出现次数超过50次了
for key, value in ip_dict.items():
if value >= 50:
print("ip:%s,已经超出50次" % key)
# file.close()
print("当前记录信息未:%s" % ip_dict)
print("=========结束本次=========")
time.sleep(5)
file.close()