python学习笔记(五)- 文件操作

时间:2023-03-09 17:52:10
python学习笔记(五)- 文件操作
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()) #把文件的每一行用\n换行,放到一个list里面
f.write('sss') #报错,默认读模式,不能写
④f.close() #每次都要关闭文件

打开绝对路径的方式:

  f = open(r'H:\pythonproject\day4\word.txt')

2、打开文件的几种方式的比较:

1、读模式(默认) r  读写模式r+
f = open('word.txt')
1)r/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读的:\n',f.read()) #文件指针到末尾
print('readline读的:\n',f.readline()) #f.readline()没有读到内容

  python学习笔记(五)- 文件操作

  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 = ''
rand_num = str(random.randint(1,9999)) #将整型转成字符串类型 new_num = rand_num.zfill(4) #不足4位数就补零,zfill是字符串的方法
phone = start + new_num
f.write(phone+'\n') #换行写入到文件 f.close()

6、直接循环一个文件对象,一行一行处理日志文件:

f = open(r'H:\pythonproject\day4\access.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、每分钟读一次

  python学习笔记(五)- 文件操作

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:\pythonproject\day4\access.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、把新的内容写进去

  python学习笔记(五)- 文件操作

f = open('user.txt','a+')  #1、打开一个文件,获取到所有的内容
f.seek(0) #a+模式,重置指针位置
all_str = f.read() #1、获取到所有的内容---字符串模式
new_str = all_str.replace('','') #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','') #替换
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('') #f.write()必须是写一个字符串
>>>123456
f.writelines('aaa,bbb,ccc') #如果是字符串就没必要用writelines()了,因为不用循环,直接用f.write()就行
>>>aaa,bbb,ccc

f.writelines(['aaa','','']) #f.writelines()可以将列表循环写入,writelines会帮我们循环一次
>>>aaa123456786

相当于f.write()循环写:
for data in l:
f.write(data)
f.close()

zz