一、文件处理流程
1.打开文件,得到文件句柄并赋值给一个变量
2.通过句柄对文件进行操作
3.关闭文件
r模式,默认模式,文件不存在则报错
w模式,文件不存在则创建,文件存在则覆盖
a模式,文件不存在则创建,文件存在则不会覆盖,写内容会以追加的方式写(写日志文件的时候常用),追加模式是一种特殊的写模式
b(rb,wb,ab)模式:不用加encoding:utf-8
f=open('c.txt','rb') print(f.read().decode()) f=open('d.txt','wb') f.write('啦啦啦'.encode('utf-8')) f.close()
二、基本操作
1.文件打开模式
文件句柄=open('文件路径',‘模式’)
打开文件时,需要指定文件路径和以什么方式打开文件。
打开文件的模式有:
- r ,只读模式【默认模式,文件必须存在,不存在则抛出异常】
- w,只写模式【不可读;不存在则创建;存在则清空内容】
- x, 只写模式【不可读;不存在则创建,存在则报错】
- a, 追加模式【可读; 不存在则创建;存在则只追加内容】
-
#只读模式 f=open(mode='r',file='练习.txt',encoding='utf-8') print('====>1',f.read()) f.readable() #判断文件是否可读 f.readline() #只读一行,遇到 或 为止,一次读一行 f.readlines() #读所有,以列表的形式保存 #写模式:文件不存在则创建,文件存在则覆盖原有的 f=open("new.py",'w',encoding='utf-8') f.write('1111111111 ') f.writelines(['2222 ','2222548 ','978646 ']) f.close() # 追加模式:文件不存在则创建,文件存在不会覆盖,写内容是追加的方式写 f=open('new.py','a',encoding='utf-8') f.write('nishishui ') f.writelines(['aa ','bb ']) f.close()
"+" 表示可以同时读写某个文件
- r+, 读写【可读,可写】先读再写
- w+,写读【可读,可写】先清空再读
- x+ ,写读【可读,可写】
- a+, 追加读【可读,可写】
"b"表示以字节的方式操作
- rb 或 r+b
- wb 或 w+b
- xb 或 w+b
- ab 或 a+b
注:以b方式打开时,读取到的内容是字节类型,写入时也需要提供字节类型,不能指定编码
-
练习,利用b模式,编写一个cp工具,要求如下:
1. 既可以拷贝文本又可以拷贝视频,图片等文件
-
f = open('sb.png','rb') data = f.read() write_f = open('sb_1.png','wb') write_f.write(data)
三、上下文管理
1. with open('a.txt','w') as f:
pass
2.with open('a.txt','r') as read_f,open('b.txt','w') as write_f:
data=read_f.read()
write_f.write(data)
-
四、文件的修改
1 #图片的形式以二进制读写 2 import os 3 with open('sb.png','rb') as read_f,open('sb_swap.png','wb') as write_f : 4 data = read_f.read() 5 write_f.write(data) 6 os.remove('sb.png') 7 os.rename('sb_swap.png','sb.png') 8 9 ###读到内存,更改。先读到内存,然后seek到0,再清空所有。然后内存中更改,再写入硬盘 10 f_old = '练习.txt' 11 old_str = '罗梦竹' 12 new_str = 'Jack' 13 f = open(f_old,'r+',encoding='utf-8') 14 data = f.readlines() 15 f.seek(0) 16 f.truncate() 17 for line in data: 18 if old_str in line : 19 line = line.replace(old_str,new_str) 20 # print(line,end='') 21 f.write(line) 22 f.close() 23 24 ###占硬盘的方式,修改文件 25 import os 26 f_old = '练习.txt' 27 f_new_name = "new_%s"%f_old 28 old_str = '罗梦竹' 29 new_str = 'Jack' 30 f = open(f_old,'r',encoding='utf-8') 31 f_new = open(f_new_name,'w',encoding='utf-8') 32 for line in f: 33 # print(line) 34 if old_str in line : 35 line = line.replace(old_str,new_str) 36 f_new.write(line) 37 f.close() 38 f_new.close() 39 os.remove(f_old) 40 os.rename(f_new_name,f_old) 41 # os.replace(f_new_name,f_old) #win下面用replace可以强制更改文件名,linux 可以直接rename
五、文件内光标移动
一: read(3):
1. 文件打开方式为文本模式时,代表读取3个字符
2. 文件打开方式为b模式时,代表读取3个字节
二: 其余的文件内光标移动都是以字节为单位如seek,tell,truncate
注意:
1. seek有三种移动方式0,1,2,其中1和2必须在b模式下进行,但无论哪种模式,都是以bytes为单位移动的
seek控制光标的移动,是以文件开头作为参照的。
tell当前光标的位置
2. truncate是截断文件,截断必须是写模式,但是不能用w或w+等方式打开,因为那样直接清空文件了,所以truncate要在r+或a或a+等模式下测试效果
- 类似tail 的操作
import time with open('tail','r',encoding='utf-8') as f: f.seek(0, 2) while True: line = f.readline().strip() if line: print("new log:",line) time.sleep(0.5)
其他:
-
###文件处理,j检测编码 # import chardet # f = open('练习.txt','rb') # data = f.read() # f.close() # result = chardet.detect(data) # print(result) ###循环文件 # f = open('练习.txt','r',encoding='utf-8') # # data = f.read() # for line in f: # print(line,end = '') # f.close() ####x写文件,写文件是把原有的清空再写入。 # f = open('练习2.txt','w',encoding='utf-8') # f.write('路飞学城!') # f.close() # f = open('练习2.txt','wb') # f.write('路飞学城!!'.encode('utf-8')) # f.close() #####追加操作 # f = open('练习2.txt','a+',encoding='utf-8') # f.write(' 路飞学城!') # f.close() ###读写混合模式 # f = open('练习2.txt','r+',encoding='utf-8') # data = f.read() # print(data) # f.write(" hello gril 1") # f.write(" hello gril 2") # f.write(" hello gril 3") # f.write(" hello gril 4") # print('new:',f.read()) # f.close() # '''w+:写读模式是限清空源文件内容。然后再重新写入''' ''' a+ 追加读 with open(。。。)as 。。。,open((。。。) as f: d逗号隔开可以多次打开 称为上下文管理 ''' # f.flush() #把文件从内存(buffer)强制刷到硬盘中 # f.readable() #判断文件是否可读 # f.readline() #只读一行,遇到 或 为止,一次读一行 # f.readlines() #读所有,以列表的形式保存 # print(f.closed) #判断文件是否是关闭状态 # print(f.encoding) #查看文件编码 # f.seek() #移动光标的位置,移动的是字节 # f.tell() #返回光标所在的位置 # f.seekable() #判断文件是否可以进行seek操作 # f.writable() #判断文件是否是可写 # f.truncate() #指定长度截断文件,里面加上值是从值开始 # f.writable() #判断文件是否可写 # f.writelines() #以列表的方式写()里面是列表或者元组
问:假如你不知道你要处理的文件是什么编码可怎么办呢?
import chardet f = open('log',mode='rb') data = f.read() f.close() result = chardet.detect(open('log',mode='rb').read()) print(result)
输出:
{'encoding': 'GB2312', 'confidence': 0.99, 'language': 'Chinese'}
注意:
文件操作时,以 “r”或“rb” 模式打开,则只能读,无法写入;
硬盘上保存的文件都是某种编码的0101010,打开时需要注意:
rb,直接读取文件保存时原生的0101010,在Python中用字节类型表示
r和encoding,读取硬盘的0101010,并按照encoding指定的编码格式进行断句,再将“断句”后的每一段0101010转换成unicode的 010101010101,在Python中用字符串类型表示练习题1 —— 全局替换程序:
-
写一个脚本,允许用户按以下方式执行时,即可以对指定文件内容进行全局替换
`python your_script.py old_str new_str filename`
-
替换完毕后打印替换了多少处内容
1 import os,sys 2 a = 0 3 if os.path.isfile(sys.argv[3]): 4 f = open(sys.argv[3],'r+',encoding='utf-8') 5 old_str = sys.argv[1] 6 new_str = sys.argv[2] 7 data = f.readlines() 8 f.seek(0) 9 f.truncate() 10 for line in data: 11 if old_str in line: 12 line = line.replace(old_str,new_str) 13 a += 1 14 f.write(line) 15 f.flush() 16 print(a) 17 f.close()
练习题2 —— 模拟登陆:
- 用户输入帐号密码进行登陆
- 用户信息保存在文件内
- 用户密码输入错误三次后锁定用户,下次再登录,检测到是这个用户也登录不了
dic_name = {'Chris':'123'} user_name = input("please input your user name:") user_pwd = input("please input your password:") with open('login', 'r', encoding='utf-8') as f: data = f.read().strip() if user_name in data: print("user lock") # exit() elif user_name in dic_name.keys(): if user_pwd == dic_name.get(user_name): print("welcome") else: print("login failed") with open('login','a+',encoding='utf-8') as f : f.write(user_name+' ') else: print("用户不存在")
-