文件的三种模式:默认为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()