python操作文件

1 python操作文件介绍

  文件是操作系统提供给应用程序操作硬盘的一个对象,一个虚拟单位,用于应用程序将数据永久保存在硬盘中.

  在python中,操作文件主要有以下几个步骤:

# 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):

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参数说明:

  其中,重要的如下:

# 对于文本文件(默认rt),读写都是以字符串为单位,需要指定字符编码
r :只读模式【默认模式,文件必须存在,不存在则抛出异常】
w :只写模式【不可读;不存在则创建;存在则清空内容】
a :追加写模式【不可读;不存在则创建;存在则只追加内容】,应用场景:日志文件
# 对于非文本文件(如图片,视频等),只能以b模式处理,且无需考虑字符编码
rb :读取时,解码decode='utf-8',可以看到原本的内容
wb :写入时,指定encode='utf-8'写入,就是bytes类型
ab
注意:以b方式打开时,读取到的内容是字节类型,写入时也需要提供字节类型,不能指定编码

  实例:

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对象对应的方法说明

  重要的方法:

#以下在没有执行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了.

with open('a.txt','r') as f1,open('b.txt','w') as f2:    #同时处理多个文件使用逗号隔开,要换行需要使用续行符 \
    data=f1.read()      #子代码块
    f2.write(data)      #子代码块 

  实例:

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.

  实例:

# 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. 文件内光标的移动

  原文本文件内容为:

张三    男    20   11122233344
李四    男    21   22233344455
王一    女    22   33344455566

  执行with语句:

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++等编辑器).缺点:文件如果过大,可能导致机器卡死.

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循环),修改完毕就写入新文件,最后用新文件覆盖源文件.(解决内存占用大的问题,但会多打开一个新文件,占用硬盘资源)

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')   #重命名

  

  

  

 

 

 

 

 

 

 

 

 

 

 

 

  

  

 

 

 

 

 

 

 

 

posted @ 2019-09-17 18:14  執著的蝸牛  阅读(342)  评论(0编辑  收藏  举报