一、文件操作简介
计算机系统分为:计算机硬件,操作系统,应用程序三部分。
我们用python或其他语言编写的应用程序若想要把数据永久保存下来,必须要保存于硬盘中,这就涉及到应用程序要操作硬件,众所周知,应用程序是无法直接操作硬件的,这就用到了操作系统。操作系统把复杂的硬件操作封装成简单的接口给用户/应用程序使用,其中文件就是操作系统提供给应用程序来操作硬盘虚拟概念,用户或应用程序通过操作文件,可以将自己的数据永久保存下来。
有了文件的概念,我们无需再去考虑操作硬盘的细节,只需要关注操作文件的流程:
open函数中模式参数的常用值:
open('文件路径') 默认的打开方式‘r’,默认的打开的编码是操作系统的默认编码
r :读模式
w :写模式
a :追加模式
b :二进制模式(可添加到其他模式中使用)
+ :读/写模式((可添加到其他模式中使用)
备注:
1)一般来说,python默认处理的是文本文件。但是处理一些其他类型的文件(二进制文件),比如声音剪辑或者图像,那么可以使用‘b’模式来改变处理文件的方法。参数‘rb’可以用来读取一个二进制文件。
2)在实际工作过程中,很少遇到又读又写的事情,尽量不要使用‘+’模式,在python3里的文件指针非常乱,读写的时候占用两个不同的指针,所以很容易产生问题
文件操作过程:
1 #1.打开文件,得到文件句柄并赋值给一个变量 2 f1=open(r'C:a.txt',encoding='utf-8',mode='r')#开头‘r’代表元素字符串的意思,代表‘’ 3 #2.通过句柄对文件进行操作 4 data=f1.read() 5 #3.关闭文件 6 f1.close() 7 #f1为python的变量,保存的文件内容,程序结束才能又python自动回收,文件关闭后不能在对文件进行读写 8 #f1为文件句柄或文件对象,可以设置变量名:file,f_handle,file_handle,f_obj 9 #open():打开的指令,windows的指令 10 #close():关闭文件,回收操作系统资源(不关闭会在内存中一直存在,切记) 11 #windows 的默认编码方式gbk,linux默认编码方式utf-8,max系统为utf-8
二、文件的读
1 # pycharm 创建的文件默认都是utf-8 notepad++默认也是utf-8,但是可以修改编码方式,在格式菜单下修改 2 # EncodeDecodeErrot:编码错误 3 # 读操作:r模式:默认是rt文本读 4 # rb模式:二进制模式,非文字类的文件操作 5 f1=open(r'register',encoding='utf-8')#不写mode,默认以读的形式打开 6 print(f1.read()) 7 f1.close()
1、read() 文件内容全部读出
read() 不传参数 意味着读所有
传参,如果是r方式打开的,参数指的是读多少个字符
传参,如果是rb方式打开的,参数指的是读多少个字节
1 f1=open(r'a.txt',mode='rb')#rb模式不用写encoding,它是以bytes类型进行读取 2 data1=f1.read() 3 print(data1) 4 data2=f1.read()#因为读文件有光标移动,第一次读之后,光标移动到最后,第二次读的时候读不到任何内容 5 print(data2) 6 f1.close() 7 8 #read(n) r模式,按照字符读取 ; rb模式,按照字节读取 9 f1=open(r'a.txt',encoding='utf-8') 10 print(f1.read(5))#r模式,按照字符读取 11 f1.close() 12 f1=open(r'a.txt',mode='rb') 13 print(f1.read(3))#rb模式,按照字节读取 14 f1.close() 15 16 # unicode - --> bytes encode() 17 # bytes - --> unicode decode() 18 f1=open(r'a.txt',mode='rb') 19 data=f1.read(3)#写2个字节报错,必须与中文对应位数 20 print(data.decode('utf-8'))#rb模式,按照字节读取 21 f1.close()
2、readline() 按行读取
readline() 一行一行读 每次只读一行,不会自动停止
1 f1=open(r'a.txt',encoding='utf-8',mode='r') 2 print(f1.readline(),end='')#end可以取消print的换行效果 3 print(f1.readline(),end='') 4 f1.close()
3、readlines() 将每一行作为列表的元素,并返回这个列表(不常用)
1 readlines() 将每一行作为列表的元素,并返回这个列表 2 # 在文件比较小的时候可以用read和readlines读取,文件过大时,不建议使用这两种方式 3 f1=open(r'a.txt',mode='rb') 4 print(f1.readlines()) 5 f1.close()
4、for 循环
for循环 一行一行读 从第一行开始 每次读一行 读到没有之后就停止
1 f1=open(r'a.txt',mode='rb')#f1这个文件句柄是迭代器,在内存当中只占一行的内存,for循环读取时,永远只在内存当中占一行 2 for line in f1: 3 print(line) 4 f1.close()
5、while 循环 不建议使用
1 with open(b'a.txt','r',encoding='utf-8') as f: 2 while True: 3 line=f.readline() 4 if len(line)==0:break 5 print(line)
三、文件的写
写操作:只能写字符串格式的,不能写数字
w模式:默认是wt文本写,如果文件不存在创建,存在则清空+覆盖
1、write()
1 f=open('a.txt','w',encoding='utf-8') 2 f.write('11111 ') 3 f.write('22222 ') 4 f.close()
2、writelines()
1 f=open('a.txt','w',encoding='utf-8') 2 f.writelines(['哈哈哈 ','hello','world']) 3 f.close()
3、writable 判断文件是否可写
1 f=open('a.txt','w',encoding='utf-8') 2 print(f.writable())#>>>True 3 f.close()
4、a模式 文件不存在则创建,文件存在在打开文件后则光标移动到文件末尾追加写
1 f=open('a.txt','a',encoding='utf-8') 2 f.write('sssss ') 3 f.close()
5、b模式
1 #b模式 bytes 可以读文本、图片、视频,文件不存在报错 2 #rb模式不能指定字符编码,否则报错 3 with open(b'1.bmp','rb') as f: 4 print(f.read())#输出图片的二进制编码 5 with open(b'a.txt','rb') as f: 6 print(f.read().decode('utf-8')) 7 8 #rt 以文本形式读取 9 with open(b'a.txt','rt',encoding='utf-8') as f: 10 print(f.read()) 11 12 #wb 13 with open(b'a.txt','wb') as f: 14 res='你好'.encode('utf-8') 15 print(res,type(res)) 16 f.write(res) 17 18 #ab 追加写 19 with open(b'a.txt','ab') as f: 20 res='你好'.encode('utf-8') 21 print(res,type(res)) 22 f.write(res)
6、copy
1 #1、源文件大小的问题,一行一行读 2 #2、文件打开模式的问题 3 #flush()方法是用来刷新缓冲器的,即将缓冲区的数据立刻写入文件,同时清空缓冲区,不需要时被动的等待输入,
#一般情况下,文件关闭后会自动刷新缓冲区,但是有时你需要在关闭前刷新它,这时就可以使用flush()方法 4 with open(b'a.txt','rb') as read_f, 5 open('dstfile','wb') as write_f: 6 for line in read_f: 7 write_f.write(line) 8 # write_f.flush() 9 10 #导入模块的好处就是可以把别人写的功能直接拿来用 11 #sys.argv是用来获取命令行参数的,sys.argv[0]表示代码本身路径,所以参数从1开始 12 import sys 13 _,src_file,dst_file=sys.argv 14 with open(src_file,'rb') as read_f, 15 open(dst_file,'wb') as write_f: 16 for line in read_f: 17 write_f.write(line) 18 # write_f.flush() 19 20 # encoding:utf-8 21 with open('a.txt','rt',encoding='utf-8') as f: 22 print(f.read()) 23 24 # with 程序运行完毕后自动关闭文件 25 with open(r'register',mode='rb') as f1: 26 pass 27 # with open() as 自动关闭文件句柄 同一个with可以操作多个文件句柄
四、文件修改
1 #文件修改 2 #1,打开原文件,产生文件句柄 3 #2,创建新文件,产生文件句柄 4 #3,读取原文件,进行修改,写入新文件 5 #4,将源文件删除 6 #5,新文件重命名原文件 7 import os 8 with open('info.txt','rt',encoding='utf-8') as read_f,open('.info.txt.swap','w',encoding='utf-8') as write_f: 9 data=read_f.read() 10 write_f.write(data.replace('你好','hello')) 11 print(data) 12 os.remove('info.txt') 13 os.rename('.info.txt.swap','info.txt') 14 15 import os 16 with open('info.txt','rt',encoding='utf-8') as read_f,open('.info.txt.swap','w',encoding='utf-8') as write_f: 17 for line in read_f: 18 if '你好' in line: 19 line=line.replace('你好','hello') 20 write_f.write(line) 21 os.remove('info.txt') 22 os.rename('.info.txt.swap','info.txt')
五、文件内光标移动
1 # tell()光标当前的位置(字节) 2 with open('a.txt','r',encoding='utf-8') as f: 3 data1=f.read() 4 print(f.tell()) 5 6 #只有一种情况光标以字符为单位,文件以rt方式打开,read(3) 7 with open('a.txt','rt',encoding='utf-8') as f: 8 print(f.read(6)) 9 print(f.tell()) 10 11 #seek() 光标移动 按照字节去调整 12 with open('a.txt','rt',encoding='utf-8') as f: 13 print(f.read(6)) 14 print(f.tell()) 15 f.seek(0) 16 print(f.read(6)) 17 18 #seek(参数)另外两种模式需要在bytes模式下移动 19 #0模式 可以在t模式下使用 20 #1模式 相对位置移动 21 #2模式 以文件末尾为参照物移动 seek(0,2),调至最后 22 with open('a.txt','rb') as f: 23 f.seek(6,0) 24 print(f.read(6))#>>>b'xbdxa0xe5xa5xbd' 25 26 with open('a.txt','rb') as f: 27 print(f.read(6)) 28 f.seek(2,1) 29 print(f.tell()) 30 print(f.read().decode('utf-8')) 31 32 with open('a.txt','rb') as f: 33 f.seek(-3,2) 34 print(f.tell()) 35 36 #tail -f access.log 打开文件读最新追加内容 37 import time 38 with open('access.log','rb') as f: 39 f.seek(0,2) 40 while True: 41 line=f.readline() 42 if line: 43 print(line,end='') 44 else: 45 time.sleep(0.05) 46 with open('access.log','a',encoding='utf-8') as f: 47 f.write('aaaaa ') 48 f.flush() 49 50 import time 51 with open('access.log','rb') as f: 52 f.seek(0,2) 53 while True: 54 line=f.readline() 55 if line: 56 print(line) 57 else: 58 time.sleep(2) 59 60 #截断文件 61 with open('access.log','a',encoding='utf-8') as f: 62 f.truncate(3)#以文件开头为参照物,截断3字节