1、读文件
f = open('word.txt',encoding='utf8') #默认打开当前目录下的文件,打开其它目录用绝对路径
#f = open('word.txt',encoding='utf-8') #如果报字符编码错误,可能因为中文问题(bbk)
#file() #python2中打开文件的的方式
①print(f.read()) #读文件,字符串类型
②print(f.readline()) #一次读取一行内容
③print(f.readlines()) #把文件的每一行用
换行,放到一个list里面
f.write('sss') #报错,默认读模式,不能写
④f.close() #每次都要关闭文件
打开绝对路径的方式:
f = open(r'H:pythonprojectday4word.txt')
2、打开文件的几种方式的比较:
1、读模式(默认) r 读写模式r+
f = open('word.txt')
1)r/r+文件不存在的话会报错(r
+文件不存在时都报错)
2)r 读模式打开的文件,不能写
3)r+ 模式打开的文件,可以写,但默认是在文件最前面写
2、写模式 w 写读模式w+
f = open('word.txt','w')
1)w/w+ 文件不存在的话,会帮你新建文件
2)w/w+ 打开一个已存在的文件,然后写,都会覆盖文件以前的内容
3)w模式,不能读,报错 比如,print(f.read()) #不能读
4)w+ 模式,不报错,但读不到内容,因为内容已经被清空了
3、追加模式 a 追加读模式a+
f = open('word1.txt','a')
1)a/a+文件不存在的话,会新建文件
2)a/a+ 都能写,不会清空原来的文件,在尾行末尾写内容
3)a模式,不能读,报错
4)a+模式,读不到内容,因为文件指针在末尾(配合f.seek(0)就能读到)
#只要沾上了r,文件不存在时都报错
#只要沾上了w,文件写时都会清空原来的内容
3、文件指针:控制读哪一行
1)r模式:文件指针
f = open('word.txt',encoding='utf8')
print('read读的:
',f.read()) #文件指针到末尾
print('readline读的:
',f.readline()) #f.readline()没有读到内容
2)a+模式:a模式默认文件指针在末尾
f = open('word.txt','a+',encoding='utf8')
print(f.read()) #a+模式,文件指针默认在文件末尾,所以读不到内容
f.write('zzzz') #但可以在末行末尾写
3)a+模式 和f.seek()一起使用:(推荐)
f = open('word1.txt','a+')
f.seek(0) #把文件指针移动到文件最前面
print(f.read()) #可以读到内容
4)
f.seek(0) #a+模式,移动指针到最前面,只能从最前面读,写还是文件末尾写
point = f.tell() #获取到当前文件指针的位置
4、打开文件且自动关闭文件的方式:
with open('word.txt','a+') as f:
for line in f:
print(line)
5、【练习1-随机产生一些手机号】
#随机生成手机号后四位,然后写到文件里面
#比如:1861111 9999 #import random
# print(random.randint(1,1000))
# print('1',zfill(4)) #不够4位,前面补0
import random
f = open('phone','w',encoding='utf-8')
num = input("请输入想要生成的手机号数量")
for i in range(int(num)):
start = '1861111'
rand_num = str(random.randint(1,9999)) #将整型转成字符串类型
new_num = rand_num.zfill(4) #不足4位数就补零,zfill是字符串的方法
phone = start + new_num
f.write(phone+'
') #换行写入到文件
f.close()
6、直接循环一个文件对象,一行一行处理日志文件:
f = open(r'H:pythonprojectday4access.log',encoding='utf-8') #打开文件句柄(文件对象) count = 0 for line in f: #直接循环一个文件对象的话,每次循环的是文件的每一行 print(count,line) #一行一行处理,不然文件太大,内存消耗大 count += 1 ip = line.split()[0] #每一行按空格分隔,取第一个元素即IP print(ip)
【例二】:监控日志文件,如果有攻击咱们的,就把IP加入黑名单
分析:
#1、打开日志文件
#2、把IP地址拿出来 #split(),按空格分隔
#3、每分钟,判断每一个IP出现的次数,如果大于50次,加入黑名单
#4、每分钟读一次
all_ip = [] f = open('access.log',encoding='utf-8') for line in f: ip = line.split()[0] all_ip.append(ip) #print(ip) all_ip_set = set(all_ip) #print(all_ip_set) for set_ip in all_ip_set: if all_ip.count(set_ip) > 50: print("攻击频繁的ip有%s" % set_ip) f.close()
【优化】:
#监控日志文件,如果有攻击咱们的,就把IP加入黑名单 #1、打开日志文件 #2、把IP地址拿出来 #split(),按空格分隔 #3、每分钟,判断每一个IP出现的次数,如果大于50次,加入黑名单 #4、每分钟读一次 import time #引入time模块,每分钟读一次 point = 0 #用于记录每次文件指针的位置 while True: #每60s循环一次 all_ips = [] f = open(r'H:pythonprojectday4access.log',encoding='utf-8') #打开文件句柄(文件对象) f.seek(point) #打开文件后,移动文件指针,每次读这一分钟的日志内容 for line in f: #直接循环一个文件对象的话,每次循环的是文件的每一行 ip = line.split()[0] #每一行按空格分隔,取第一个元素即IP all_ips.append(ip) #将所有的ip放入空列表 point = f.tell() #记每次读文件后记录文件指针的位置(以前读过的文件就不需要读了) all_ips_set = set(all_ips) #集合去重 for set_ip in all_ips_set: if all_ips.count(set_ip)> 50: #拿集合里面没有重复的ip到all_ips里面去判断次数是否大于50 print('应该加入黑名单的ip是:%s' % set_ip) #拿出集合中大于50次的,执行linux命令加入黑名单 f.close() time.sleep(60) #暂停60s,每一分钟读一次
七、fw.flush()强制把内存缓冲区里的数据写到磁盘上
#有时候写完东西,并没有写到文件里,是因为内存有缓冲区,缓冲区满,才会写到磁盘上
fw = open('user','w') fw.write('www') fw.flush() #强制把缓冲区里的数据写到磁盘上
八、修改文件的两种方式
1)方式一、简单粗暴直接:replace()
1、打开一个文件,获取到所有的内容
2、对内容进行修改
3、清空原来的内容
4、把新的内容写进去
f = open('user.txt','a+') #1、打开一个文件,获取到所有的内容 f.seek(0) #a+模式,重置指针位置 all_str = f.read() #1、获取到所有的内容---字符串模式 new_str = all_str.replace('123456','11111') #2、修改 f.seek(0) #3、把文件指针移动到文件最前面,再清空 f.truncate() #3、清空原来的内容 f.write(new_str) #4、把新的所有的内容重新写进去 f.close()
【例三】:将文件的每一行前面都加上一个'sys_',或者将每行的'xyz_',变成'xxx_'
f = open('a.log','r+',encoding='utf-8') #用w会清空,读不到内容;用r不能写(可以r+) f.seek(0) #指针置0 all_str = '' # all_data = f.readlines() # print(all_data) for line in f: #直接读文件是字符串 #zhangsan,11111 # new_line = 'xyz_' + line #将每行的前面加前缀 new_line = line.replace('xyz_', 'xxx_') # 将每行的'xyz_',变成'xxx_' all_str = all_str + new_line #将修改后的每行放在字符串中 f.seek(0) #指针置0 f.truncate() #清空以前的内容 f.write(all_str) f.close()
>>>syz_zhangsan,123
syz_lisi,123
syz_wuang,23245
2)方式二:高效的方式:一行一行修改,然后修改“隐藏文件”的文件名
# 1、打开2个文件,a、b(a.txt、a.txt.bak)
# 2、每修改一行a文件的,就写一行到b(a.txt.bak)文件
# 3、删掉a文件,把b文件(a.txt.bak)的名字名成a文件(a.txt)
import os with open('word.txt',encoding='utf-8') as fr,open('.word.bak','w',encoding='utf-8') as fw: for line in fr: #循环取a文件 new_line = line.replace('a','1111') #替换 fw.write(new_line) #循环写入b文件 os.remove('word.txt') #删除a文件 os.rename('.word.bak','word.txt') #将b改名为a
九、f.write()和f.writeline()的区别:
f = open('user.txt','w',encoding='utf-8') f.write('123456') #f.write()必须是写一个字符串 >>>123456 f.writelines('aaa,bbb,ccc') #如果是字符串就没必要用writelines()了,因为不用循环,直接用f.write()就行 >>>aaa,bbb,ccc
f.writelines(['aaa','123456','786']) #f.writelines()可以将列表循环写入,writelines会帮我们循环一次 >>>aaa123456786
相当于f.write()循环写: for data in l: f.write(data) f.close()
zz