一,文件操作
(一),文件处理流程
1,打开文件,获得文件句柄(open函数提供)并赋值
2,通过句柄对文件进行操作
3,关闭句柄
f = open('陈粒',encoding='utf-8')#open函数会先检索系统的编码gbk,文件存的是UTF-8编码,这样会出现乱码 data = f.read() print(data) f.close() f = open('XXX')#把XXX使用gbk编码保存在硬盘上,然后打开不会乱码 data = f.read() print(data) f.close()
(二),文件打开模式:
1,文件读操作,r只读
f = open('XXX','r')#XXX使用gbk编码 #data = f.read() #print(data) #输出文件内容 print(f.readable())#是否可读 #输出True # print('第一行',f.readline(),end='')#readline,一次读取一行 # print('第二行',f.readline())#注意如果前面的f.read()读取了文件内容,则使用readline时,游标在文件尾,print不会显示内容 # print('第三行',f.readline())#如果文件没有第三行,则输出空,此时游标在文件尾 print('读取到列表',f.readlines()) #输出:读取到列表 ['1111\n', '2222\n', '\n'] f.close()
2,文件写操作,w只写
f = open('陈粒2','w',encoding='utf-8')#w写模式如果文件存在会把文件清空后再操作,文件不存在则新建 #f.read()#使用写模式打开,读会报错 #输出:io.UnsupportedOperation: not readable f.write('11111\n') f.write('22222\n') f.write('333\n444\n555\n') #f.writable() f.writelines(['666\n','777'])#写一个列表到文件 #f.writelines(['666\n','777',1])#写的内容必须是字符串,如果有数字存在会报错 #输出:TypeError: write() argument must be str, not int f.close()
3,文件追加操作,a添加
f = open('陈粒2','a',encoding='utf-8') f.write('\n写到文件最后') f.close()
4,文件处理其它模式,r+,可读,可写
#r+模式,可读可写 f = open('陈粒2','r+',encoding='utf-8') data = f.read() print(data) f.write('写测试') f.close()
5,文件处理B(二进制)模式
1),open默认使用t方式(文本)打开文件,但如果文件是图片,视频等就不适用文本方式打开,需要改用b方式打开
2),二进制方式可以跨平台使用
3),使用举例:
#读二进制方式打开rb,需要解码
#f = open('test11.py', 'rb', encoding='utf-8') # b的方式不能指定编码 f = open('test11.py', 'rb') data = f.read() #'字符串'---------encode---------》bytes #bytes---------decode---------》'字符串' print(data.decode('utf-8')) #要想显示正常,需要decode,并指定解码类型
#写二进制方式打开wb,需要编码 f = open('test22.py','wb') #f.write('11111\n') #报错,字符串以二进制形式写入,需要指定编码类型 f.write(bytes('11111\n',encoding='utf-8'))#使用bytes函数转换 f.write('杨戬'.encode('utf-8')) #使用字符串本身的encode方法转换
#追加二进制方式ab,在文件最后一个位置添加 f = open('test22.py','ab') f.write('yangjian'.encode('utf-8'))
(三),文件处理的一些方法
写文件时游标的位置
#打开文件后,游标位于开头,故从开头开始写,覆盖原有内容 f = open('陈粒2','r+',encoding='utf-8') test = '写在头部' test1 = bytes(test,encoding='utf-8') print(len(test1)) #输出:12 表示占用12个字节 test2 = '111\n222\n33' print(len(test2)) #输出:10 表示占用10个字节 f.write(test) #在陈粒2文件的开头部分 111\n222\n33 被'写在头部'占用,从字节上看差了2个 f.close()
readlines和writelines操作列表,每一行是一个列表元素
#文件修改,只剩第一行 src_f = open('xxx','r',encoding='gbk') data = src_f.readlines() src_f.close() dst_f = open('xxx','w',encoding='gbk') dst_f.writelines(data[0]) dst_f.close()
打开文件后,无需手动关闭,使用关键字with
with open('a.txt','w') as f: f.write('1111\n') #使用with,复制文件内容到新文件 #src_f=open('xxx','r',encoding='gbk') #dst_f=open('xxx','w',encoding='gbk') with open('xxx','r',encoding='gbk') as src_f,\ open('xxx_new','w',encoding='gbk') as dst_f: data=src_f.read() dst_f.write(data)
flush,tell,newline=
f = open('a.txt','r',encoding='utf-8') #f.close() print(f.closed) #文件是否关闭 print(f.encoding)#文件打开的编码,跟源文件在硬盘上怎么存储没有关系 #f.flush()#从内存保存到硬盘,可以在终端内测试,打开文件写入内容,但是硬盘上文件并没有内容,然后使用flush保存再查看内容 print(f.tell())#当前游标所在位置 0 f.readline()#读取一行移动游标到行尾 print(f.tell())#当前游标所在位置 f.close() f = open('a.txt','r',encoding='utf-8',newline='')#使用newline关键字不让python自动处理\r,自动处理是python为跨平台准备的 print(f.readlines()) f.close() #输出:['你好,你好\r\n']
注意:read(3)代表读取3个字符,其余的文件内游标移动都是以字节为单位,如seek,tell,truncate
#f.read()读取的是字符,不是字节 f = open('a.txt','r',encoding='utf-8') print(f.read(3)) print(f.tell())#read以字符计算,但是tell仍以字节计算 f.close() #输出 ''' 你好, 9 '''
seek游标位置移动
f = open('a.txt','r',encoding='utf-8') print(f.tell()) f.seek(3) print(f.tell()) print(f.read()) f.close() #输出 ''' 0 3 好,你好 '''
#seek补充 #1模式,相对位置 f = open('seek.txt','rb') print(f.tell()) f.seek(10) print(f.tell()) f.seek(3) print(f.tell()) #输出:3,默认从文件头开始计算 f.seek(5,1) #1模式,相对上一次位置移动,但是打开文件方式必须加b,二进制方式打开。二进制打开不能指定编码 print(f.tell()) #输出:8 f.close() #2模式,文件尾往回数 f = open('seek.txt','rb') print(f.tell()) f.seek(-5,2) #2模式,从文件末尾开始seek,但是seek值必须是负数 print(f.tell()) print(f.read()) #输出b'\r\n123 f.close() #循环文件技巧 f = open('日志文件','rb') for i in f: #使用f而不是f.readlines(),可以避免在内存中生成大列表 print(i) f.close() #使用场景,日志文件很大,一般读取最后一行 f = open('日志文件','rb') for i in f: offs = -3 while True: f.seek(offs,2) data = f.readlines() if len(data) > 1: #如果倒数读取了一行多,打印,结束循环 print('最后一行%s'%(data[-1].decode('utf-8'))) break offs *= 2 #如果还不到一行,增加offs继续试探 #输出:最后一行2016/12/30 sb 干了件sb事情
truncate文件截断,属于先读文件后写文件,一般r+打开
f = open('a.txt','r+',encoding='utf-8') f.truncate(6)#从文件头开始保留6个字节,其余删除