python操作文件
1 python操作文件介绍
文件是操作系统提供给应用程序操作硬盘的一个对象,一个虚拟单位,用于应用程序将数据永久保存在硬盘中.
在python中,操作文件主要有以下几个步骤:
1 2 3 4 5 6 7 | # 1. 打开文件,得到文件句柄并赋值给一个变量,其完整的格式如下: f = open ( 'file' , mode = 'r' , buffering = - 1 , encoding = None , errors = None , newline = None , closefd = True , opener = None ) # 2. 通过句柄对文件进行操作(读/写/追加等) data = f.read() # 3. 关闭文件,回收操作系统的资源(关闭后,文件已不可打开,因为操作系统方面的资源已被关闭) f.close() # 4. 删除文件del f ,此步骤可以忽略不写(应用程序级别),因为python解释器有自动的垃圾回收机制,但删除步骤del f,必须放在f.close之后. |
open()函数中接收的参数解释(常用的是file,mode,encoding):
1 2 3 4 5 6 7 8 | file : 必需,文件路径(相对或者绝对路径),注意windows系统下通常需要在前面加 r ,防止转义 mode: 可选,文件打开模式,默认是rt,即以只读方式打开文本文件 buffering: 设置缓冲 encoding: 可选,操作文件使用的字符编码,一般使用utf8,如果不指定,就以操作系统的字符编码打开文件(编码不对会乱码) errors: 报错级别 newline: 区分换行符 closefd: 传入的 file 参数类型 opener: |
1.1 f=open()过程分析及mode参数说明
过程:
1)由应用程序向操作系统发起系统调用open(...).
2)操作系统打开该文件,并返回一个文件句柄给应用程序.
3)应用程序将文件句柄赋值给变量f.
注意:open()打开的是本机上文件,并且,open()函数内无论是读/写/追加内容,统一使用 \n 作为换行符.
mode参数说明:
其中,重要的如下:
1 2 3 4 5 6 7 8 9 | # 对于文本文件(默认rt),读写都是以字符串为单位,需要指定字符编码 r :只读模式【默认模式,文件必须存在,不存在则抛出异常】 w :只写模式【不可读;不存在则创建;存在则清空内容】 a :追加写模式【不可读;不存在则创建;存在则只追加内容】,应用场景:日志文件 # 对于非文本文件(如图片,视频等),只能以b模式处理,且无需考虑字符编码 rb :读取时,解码decode = 'utf-8' ,可以看到原本的内容 wb :写入时,指定encode = 'utf-8' 写入,就是bytes类型 ab 注意:以b方式打开时,读取到的内容是字节类型,写入时也需要提供字节类型,不能指定编码 |
实例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | f = open ( 'b.txt' ,encoding = 'utf-8' ) #这样写,默认省略了mode='rt',不能只写t,不写r,会报错,可以只写r,不写t f = open ( 'b.txt' ,encoding = 'utf-8' ) #mode='w',文件中内容会被覆盖,无此文件会新创建 data = f.write( 'asdasd' ) #只读模式下不可写,not writable f = open ( 'b.txt' ,mode = 'w' ,encoding = 'utf-8' ) #mode='w',文件中内容会被覆盖,无此文件会新创建 f.write( 'aaaaaaaa\nbbbbbbbb\n' ) data = f.read() #只写模式下不可读,not readable f = open ( 'b.txt' ,mode = 'rt' ,encoding = 'utf-8' ) print (f.readline(),end = ' ') #print自带换行,readline以行为单位读取,不加end=' '会多一行空行 with open ( 'b.txt' ,mode = 'w' ,encoding = 'utf-8' ) as f: f.write( 'aaaaa\nbbbbb\n' ) #每写完一行,光标移到最后 f.write( 'ccccc\nddddd\n' ) #只写模式下需要自己加换行符 \n with open ( 'b.txt' ,mode = 'w' ,encoding = 'utf-8' ) as f: f.writelines([ '111111\n' , '222222\n' , '3333333\n' ]) #相当于for循环列表内元素后放到文件中,对应readlines() with open ( 'b.txt' ,mode = 'w' ,encoding = 'utf-8' ) as f: f.write( '111111\n22222\n333333' ) #此种模式下写入,只可以接收字符串,不像writelines()列表,可以是所有数据类型 # a 模式,追加写模式,通常用于日志文件,文件存在时,追加内容,光标移到末尾,文件不存在则创建空文件并追加内容 with open ( 'b.txt' ,mode = 'a' ,encoding = 'utf-8' ) as f: f.write( '111111\n' ) #追加写模式,每次追加写光标都在末尾,需要手工添加换行符 \n ,确定是否换行 |
1.2 file对象对应的方法说明
重要的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #以下在没有执行f.close()的情况下,资源还未关闭,有文件光标的概念 f.read() #刚打开时,光标停在内容开头,当读取完所有内容,光标移动到文件末尾 f.readline() #以行为单位读取文件内容,读取完一行内容后,光标会移动到第二行首部(文件过大,读取可能会卡死) f.readlines() #读取所有内容,以行分隔每一行内容,并存放于列表中,读完后,光标移到最后(文件过大,可能会卡死) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - f = open ( 'b.txt' ,mode = 'rt' ,encoding = 'utf-8' ) print (f.readlines()) #['aaaaaaaa\n', 'bbbbbbbb\n']以行为单位切分为一个列表,对应writelines([list]) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - f.write( '1111\n222\n' ) #针对文本模式的写,需要自己写换行符 f.write( '1111\n222\n' .encode( 'utf-8' )) #针对b模式的写,需要自己写换行符 f.writelines([ '333\n' , '444\n' ]) #文件模式,对应读的readlines f.writelines([bytes( '333\n' ,encoding = 'utf-8' ), '444\n' .encode( 'utf-8' )]) #b模式 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - f.readable() #判断文件是否可读,可读返回True,否则返回False f.writable() #文件是否可写,可写返回True,否则返回False f.closed #判断文件是否关闭,是返回True,否则返回False f.encoding #如果文件打开模式为b,则没有该属性 f.flush() #立刻将文件内容从内存刷到硬盘 f.name |
1.3 小结
每打开一个文件,操作系统都要分配一个文件描述符(文件描述符有限),并维护此文件的打开状态,返回一个值给应用程序.
关于对文件操作的方法,如open(),f.read(),f.close(),都涉及到系统调用,因为应用程序无法直接对硬件进行操作.任何对于硬件的操作,都需要通过操作系统来发起系统调用systemcall,来转换为底层的硬件操作.
使用open()函数的常用形式是接收2个参数:文件名(file)和模式(mode),使用open()打开一个文件,包含了2个方面的资源:操作系统打开的文件+应用程序的变量,所以在操作完一个文件,必须把这2个方面的资源一起回收.因为python有自动垃圾回收机制,所以,应用程序的资源可以忽略,但操作系统的资源补必须手动回收,即f.close().
常用 with 关键字,来管理上下文,避免忘记 f.close.
1.4 利用关键字with管理上下文
with关键字的作用:管理上下文,即打开文件,完成操作后,自动回收资源,无需close了.
1 2 3 | with open ( 'a.txt' , 'r' ) as f1, open ( 'b.txt' , 'w' ) as f2: #同时处理多个文件使用逗号隔开,要换行需要使用续行符 \ data = f1.read() #子代码块 f2.write(data) #子代码块 |
实例:
1 2 3 4 5 6 7 8 9 | with open ( 'b.txt' ,encoding = 'utf-8' ) as f: #此种方式不会造成内存被撑爆,读一行取一行 for line in f: print (line,end = '') - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - for line in f.readlines(): #此种方式可能会造成系统卡顿(文件过大)甚至崩溃 print (line,end = '') #因为是一次性读 结果 - - - - - - - - - - - - - - - - - - - - - - - - - - aaaaaaaa bbbbbbbb |
1.5 b模式下对文件的操作
操作文本文件,默认以rt模式操作,只能对文本文件操作,不能对非文本文件进行操作.
以b模式可以操作文本文件,读写都是以bytes为单位,可以进行encode编码/decode解码操作.
b模式下操作图片,视频等其他文件,不能进行decode操作.
对所有类型的文件操作,最好使用b模式,b模式具有跨平台性,但需要对数据做转换,即encode.
实例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | # b 模式,不能单独使用,必须是rb/wb/ab # b 模式下读写都是以bytes为单位,无需考虑字符编码的问题,不能也无需指定encoding参数 with open ( '1.jpg' ,mode = 'rb' ) as f: data = f.read() #文件不存在会报错No such file or directory print (data, type (data)) #图片格式底层也是用bytes字节串/二进制存储 with open ( 'b.txt' ,mode = 'rb' ) as f: #b模式下,读取文本文件(文本中存在且有内容) data = f.read() print (data, type (data)) print (data.decode( 'utf-8' )) #解码decode才可以看到对应文件中的内容(以什么编码就以什么解码),显示在pycharm工具中 with open ( 'c.txt' ,mode = 'wb' ) as f: msg = '阿萨德' data = f.write(msg.encode( 'utf-8' )) #b模式下需指定编码encode写入内容至文件中,文件中内容为 阿萨德 with open ( 'c.txt' ,mode = 'rb' ) as f: data = f.read() print ( type (data)) #<class 'bytes'>字节串类型 print (data.decode( 'utf-8' )) #读取的文件内容为阿萨德,指定编码读内容 with open ( 'c.txt' ,mode = 'ab' ) as f: f.write( '撒旦' .encode( 'utf-8' )) #指定encode追加写入 with open ( '1.jpg' ,mode = 'rb' ) as f: for line in f: print (line) #b模式下,读取图片格式的每行内容 |
2. 文件内光标的移动
原文本文件内容为:
1 2 3 | 张三 男 20 11122233344 李四 男 21 22233344455 王一 女 22 33344455566 |
执行with语句:
1 2 3 4 5 6 7 8 9 | with open ( 'c.txt' , 'r+' ,encoding = 'utf-8' ) as f: #使用r+,光标在开头 f.seek( 9 ) #指定偏移量,光标从开头往后移动3个位置(注意偏移量单位是字节) print (f.tell()) #查看当前光标位置 print (f.read()) #上面指定了偏移量,这里读出来的结果会跳过光标之前的内容 - - - - - - - - - 读出的结果 9 男 20 11122233344 李四 男 21 22233344455 王一 女 22 33344455566 |
3 python修改文件的2种方式
注意:硬盘内的数据的修改都是以新的覆盖旧的.
1)将硬盘存放的该文件的内容全部加载到内存,在内存中修改,修改完毕后,再把结果由内存覆盖到硬盘(word,vim,nodpad++等编辑器).缺点:文件如果过大,可能导致机器卡死.
1 2 3 4 5 | with open ( 'c.txt' ,mode = 'r' ,encoding = 'utf-8' ) as f: data = f.read() data = data.replace( '张三' , '张三三' ) #replace替换内容,注意这里仅仅是在内存中替换,并没有写到硬盘 with open ( 'c.txt' ,mode = 'w' ,encoding = 'utf-8' ) as f: f.write(data) #内存中已有替换的内容被写入到硬盘 |
2)建议使用:以读的方式打开原文件,将硬盘存放的该文件的内容一行一行地读入内存(for循环),修改完毕就写入新文件,最后用新文件覆盖源文件.(解决内存占用大的问题,但会多打开一个新文件,占用硬盘资源)
1 2 3 4 5 6 7 8 9 10 11 | import os with open ( 'c.txt' ,mode = 'r' ,encoding = 'utf-8' ) as f_read,\ open ( 'cc.txt' ,mode = 'w' ,encoding = 'utf-8' ) as f_write: for line in f_read: if '李四' in line: line = line.replace( '李四' , '李四四' ) f_write.write(line) #这里跟判断无关 os.remove( 'c.txt' ) #删除 os.rename( 'cc.txt' , 'c.txt' ) #重命名 |
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步