“Python文件的使用”的版本间的差异
(→练习) |
|||
(未显示同一用户的34个中间版本) | |||
第4行: | 第4行: | ||
open(file, mode='r', buffering=-1, encoding=None, errors=None,newline=None, closefd=True, opener=None) | open(file, mode='r', buffering=-1, encoding=None, errors=None,newline=None, closefd=True, opener=None) | ||
− | * | + | *file参数指定了被打开的文件路径。 |
*mode参数指定了打开文件后的处理方式。 | *mode参数指定了打开文件后的处理方式。 | ||
*buffering参数指定了读写文件的缓存模式。0表示不缓存,1表示缓存,如大于1则表示缓冲区的大小。默认值是缓存模式。 | *buffering参数指定了读写文件的缓存模式。0表示不缓存,1表示缓存,如大于1则表示缓冲区的大小。默认值是缓存模式。 | ||
第12行: | 第12行: | ||
文件打开模式: | 文件打开模式: | ||
*[[文件:python7-1.png]] | *[[文件:python7-1.png]] | ||
+ | python文件打开模式: | ||
+ | |||
+ | *b模式:以二进制模式打开文件 | ||
+ | *t模式:以文本模式打开文件 | ||
+ | *r模式:以读模式打开文件,如文件不存在则抛出异常 | ||
+ | *w模式:以写模式打开文件,如果文件已存在,则清空原有内容 | ||
+ | *x模式:以写模式打开文件,如果文件已存在,则抛出异常 | ||
+ | *a模式:以追加写模式打开文件,不覆盖文件原有内容 | ||
+ | *+模式:以读、写模式打开文件,既能读,又能写。 | ||
+ | |||
+ | |||
+ | *文件写模式:w 代表清空文件原有内容,a 代表在文件原有内容上追加,x 代表创建新文件,如果文件已存在,则抛出异常 | ||
+ | |||
====使用方法==== | ====使用方法==== | ||
*如果执行正常,open()函数返回1个文件对象,通过该文件对象可以对文件进行读写操作。如果指定文件不存在、访问权限不够、磁盘空间不足或其他原因导致创建文件对象失败则抛出异常。 | *如果执行正常,open()函数返回1个文件对象,通过该文件对象可以对文件进行读写操作。如果指定文件不存在、访问权限不够、磁盘空间不足或其他原因导致创建文件对象失败则抛出异常。 | ||
第29行: | 第42行: | ||
fr = open(r"d:\sample123.txt","r") | fr = open(r"d:\sample123.txt","r") | ||
print(fr.read()) | print(fr.read()) | ||
− | |||
fr.close() | fr.close() | ||
</nowiki> | </nowiki> | ||
注:写路径时,前面要加上字母r ,表示按照字符的原义去理解路径中的字符 | 注:写路径时,前面要加上字母r ,表示按照字符的原义去理解路径中的字符 | ||
+ | |||
+ | 文件操作属于I/O操作,I/O操作中可能因为I/O设备的原因有时操作不正确,因此I/O操作一般建议使用try语句捕获有可能发生的错误。 | ||
+ | |||
+ | <nowiki> | ||
+ | try: | ||
+ | f=open(“c:\\xyz.txt”,“rt”) | ||
+ | f.close() | ||
+ | except: | ||
+ | print("文件打开失败")</nowiki> | ||
+ | |||
+ | ====练习==== | ||
+ | 输入若干个学生的姓名Name、性别Gender、年龄Age,把它存储到文件students.txt中,每个数据项占一行。 | ||
+ | |||
+ | <nowiki>def write(info):#定义函数,写文件 | ||
+ | try:#加入异常处理语句 | ||
+ | fw = open(r"d:/test.txt","wt")#以文本写的方式打开文件 | ||
+ | fw.write(info[0]+"\n")#写入内容 | ||
+ | fw.write(info[1]+"\n") | ||
+ | fw.write(info[2]+"\n") | ||
+ | fw.close() | ||
+ | except Exception as e: | ||
+ | print(e) | ||
+ | |||
+ | def myinput( ):#接受用户输入 | ||
+ | s =input("请输入姓名,性别 年龄,以空格隔开") | ||
+ | info = [ ] | ||
+ | info = s.split( )#分割字符串 | ||
+ | return info | ||
+ | |||
+ | def read():#定义函数,读文件 | ||
+ | try: | ||
+ | fr = open(r"d:/test.txt","rt")#以文本读的方式打开文件 | ||
+ | result = fr.read() | ||
+ | return result | ||
+ | except Exception as e: | ||
+ | print(e) | ||
+ | return "error:",+str(e) | ||
+ | if __name__=="__main__": | ||
+ | info = myinput() | ||
+ | print(info) | ||
+ | write(info) | ||
+ | r = read( ) | ||
+ | print(r) | ||
+ | </nowiki> | ||
===文件的类型=== | ===文件的类型=== | ||
第41行: | 第97行: | ||
二进制文件直接由比特0和皮特一组成,没有统一的字符编码。二进制文件由于没有统一的字符编码,只能当做字节流,而不能看作是字符串。 | 二进制文件直接由比特0和皮特一组成,没有统一的字符编码。二进制文件由于没有统一的字符编码,只能当做字节流,而不能看作是字符串。 | ||
+ | |||
+ | '''当用二进制方法写文件时,必须将字符串用encode函数编一下码''' | ||
例题: | 例题: | ||
− | <nowiki># | + | <nowiki> |
− | s = ' | + | #以文本形式写文件 |
+ | s = '新年都未有芳华,二月初惊见草芽。\n白雪却嫌春色晚。故穿庭树作飞花。\n' | ||
fw = open('sample.txt',"wt") | fw = open('sample.txt',"wt") | ||
fw.write(s) | fw.write(s) | ||
第54行: | 第113行: | ||
fr.close() | fr.close() | ||
+ | #以二进制形式写文件 | ||
+ | fw = open('sample.txt',"wb") | ||
+ | fw.write(s.encode("gbk")) | ||
+ | fw.close() | ||
#以二进制形式读文件 | #以二进制形式读文件 | ||
fr =open('sample.txt',"rb") | fr =open('sample.txt',"rb") | ||
+ | print(fr.read()) | ||
+ | fr.close() | ||
+ | #以文本形式读文件 | ||
+ | fr =open('sample.txt',"rt") | ||
print(fr.read()) | print(fr.read()) | ||
fr.close()</nowiki> | fr.close()</nowiki> | ||
+ | |||
+ | |||
+ | '''文件读写结束时,一定要加入fr.close() 来关闭输入输出流。''' | ||
+ | |||
+ | ===文件的遍历=== | ||
文本文件可以看作是由行组成的组合类型,因此也可以使用遍历循环逐行的遍历文件。 | 文本文件可以看作是由行组成的组合类型,因此也可以使用遍历循环逐行的遍历文件。 | ||
第70行: | 第142行: | ||
print(line) | print(line) | ||
fp.close()</nowiki> | fp.close()</nowiki> | ||
+ | |||
+ | '''可以用for循环来逐行读入文件数据''' | ||
+ | |||
+ | ==文件的编码== | ||
+ | ===GBK编码=== | ||
+ | 是指中国的中文字符,其它它包含了简体中文与繁体中文字符,另外还有一种字符“gb2312”,这种字符仅能存储简体中文字符。 | ||
+ | |||
+ | GBK中一个英文字符占一个字节(ASCII),一个汉字两字节 | ||
+ | |||
+ | ===UTF-8编码=== | ||
+ | 它是一种全国家通过的一种编码,如果你的网站涉及到多个国家的语言,那么建议你选择UTF-8编码。 | ||
+ | |||
+ | UTF-8中一个英文字符占一个字节(ASCII),一个汉字通常占3字节 | ||
+ | |||
+ | '''保存包括中文在内的多语言文件,一般用UTF-8编码较多''' | ||
+ | |||
+ | '''在中文Windows系统中如果我们不指定文本文件的编码,那么它采用系统默认的GBK编码'''。 | ||
+ | |||
+ | '''如果我们想改变默认编码方式,在open函数中添加参数:encoding="utf-8''' | ||
+ | |||
+ | 如: fobj=open("c:\\abc.txt","wt",encoding="utf-8") | ||
+ | |||
+ | '''用utf-8编码写文件,稍后读的时候也需用utf-8编码来读,否则会报错。''' | ||
+ | |||
+ | 例6-3-1: GBK编码 | ||
+ | |||
+ | <nowiki>fobj=open("c:\\abc.txt","wt") | ||
+ | fobj.write("abc我们") | ||
+ | fobj.close()</nowiki> | ||
+ | |||
+ | 执行后abc.txt文件是7个字节,分别是: | ||
+ | |||
+ | 0x61 0x62 0x63 0xce 0xd2 0xc3 0xc7 | ||
+ | |||
+ | 其中前3个是abc字符,0xce,0xd2这2个字节是汉字"我"的内码,0xc3,0xc7这2个字节是汉字"们"的内码。 | ||
+ | |||
+ | ===指定文件编码=== | ||
+ | 如果我们不使用默认的编码,可以在open函数中用encoding参数指定编码。 | ||
+ | |||
+ | fobj=open("c:\\abc.txt","wt",encoding="utf-8") | ||
+ | fobj.write("abc我们") | ||
+ | fobj.close() | ||
+ | |||
+ | |||
+ | 执行后abc.txt文件是9个字节,分别是: | ||
+ | |||
+ | 0x61 0x62 0x63 0xe6 0x88 0x91 0xe4 0xbb 0xac | ||
+ | |||
+ | 其中前3个是abc字符,0xe6, 0x88, 0x91这3个字节是汉字"我"的UTF-8编码,0xe4,0xbb ,0xac这3个字节是汉字"们"的UTF-8编码。 | ||
+ | |||
+ | ====练习==== | ||
+ | 用UTF-8编码存储文本文件,再用相同编码读取文件。 | ||
+ | |||
+ | 思考:如果用其他的编码方式读取,会出现什么结果? | ||
+ | |||
+ | <nowiki> | ||
+ | s="队名:精神小伙 队员:张三 李四 王五\n \t" | ||
+ | |||
+ | fw = open(r"C:\Users\maxin\Documents\teaching\2023Python程序设计\1.txt",'wb')#以二进制模式写 | ||
+ | fw.write(s.encode("utf-8")) | ||
+ | fw.close()#这句不能忽略 | ||
+ | |||
+ | fr = open(r"C:\Users\maxin\Documents\teaching\2023Python程序设计\1.txt",'rb')#以二进制模式读 | ||
+ | print(fr.read( )) | ||
+ | fr.close()#这句不能忽略 | ||
+ | |||
+ | fw = open(r"C:\Users\maxin\Documents\teaching\2023Python程序设计\1.txt",'wt',)#以文本模式写 | ||
+ | fw.write(s) | ||
+ | fw.close()#这句不能忽略 | ||
+ | |||
+ | fr = open(r"C:\Users\maxin\Documents\teaching\2023Python程序设计\1.txt",'rt')#以文本模式读 | ||
+ | print(fr.read( )) | ||
+ | fr.close()#这句不能忽略 | ||
+ | |||
+ | fw = open(r"C:\Users\maxin\Documents\teaching\2023Python程序设计\1.txt",'at')#以文本模式追加写 | ||
+ | fw.write(s) | ||
+ | fw.close()#这句不能忽略 | ||
+ | |||
+ | fw = open(r"C:\Users\maxin\Documents\teaching\2023Python程序设计\1.txt",'a')#省略t字母 | ||
+ | fw.write(s) | ||
+ | fw.close()#这句不能忽略 | ||
+ | |||
+ | fr = open(r"C:\Users\maxin\Documents\teaching\2023Python程序设计\1.txt",'r+')#既能读,又能写 | ||
+ | print(fr.read( )) | ||
+ | fr.close()#这句不能忽略 | ||
+ | |||
+ | |||
+ | </nowiki> | ||
==上下文管理语句with== | ==上下文管理语句with== | ||
− | + | '''在实际开发中,读写文件应优先考虑使用上下文管理语句with,关键字with可以自动管理资源,不论因为什么原因(哪怕是代码引发了异常)跳出with块,总能保证文件被正确关闭''',并且可以在代码块执行完毕后自动还原进入该代码块时的上下文,常用于文件操作、数据库连接、网络连接、多线程与多进程同步时的锁对象管理等场合。 | |
<nowiki> | <nowiki> | ||
with open(filename, mode, encoding) as fp: | with open(filename, mode, encoding) as fp: | ||
第88行: | 第248行: | ||
with open('sample.txt',"r") as fr: | with open('sample.txt',"r") as fr: | ||
print(fr.read())</nowiki> | print(fr.read())</nowiki> | ||
+ | |||
+ | '''可以用上下文管理语句with 来简写文件输入输出''' | ||
==文件的读写函数== | ==文件的读写函数== | ||
===f.read()=== | ===f.read()=== | ||
如果文件不大,可以一次性将文件内容读入,保存到程序内部变量当中,f.read()是最常用的一次性读文件的函数。 | 如果文件不大,可以一次性将文件内容读入,保存到程序内部变量当中,f.read()是最常用的一次性读文件的函数。 | ||
+ | |||
+ | 函数调用的形式为: | ||
+ | |||
+ | <nowiki>文件对象.read() | ||
+ | 文件对象.read(n)</nowiki> | ||
+ | |||
+ | *如果不指定要读取的字符数n,使用read()读,则读到整个文件的内容; | ||
+ | *如果使用read(n)指定要读取的字符数,那么就按要求读取n个字符; | ||
+ | *如果要读n个字符,而文件没有那么多字符,那么就读取所有文件内容。 | ||
+ | *如果文件指针已经到了文件的尾部,再读就返回一个空串。 | ||
+ | |||
<nowiki>#写文件 | <nowiki>#写文件 | ||
第103行: | 第276行: | ||
print(fr.read()) | print(fr.read()) | ||
fr.close()</nowiki> | fr.close()</nowiki> | ||
+ | |||
+ | ====练习==== | ||
+ | 例6-4-3:保存文件c:\abc.txt,打开文件一次读一个字符,读取全部 | ||
+ | |||
+ | ===readline()=== | ||
+ | 如果要从文件中读取一行,那么可以使用readline() | ||
+ | |||
+ | 规则: | ||
+ | |||
+ | 它返回一行字符串。readline()的规则是在文件中连续读取字符组成字符串,一直读到'\n'字符或者读到文件尾部为止。 | ||
+ | |||
+ | 注意如果读到'\n',那么返回的字符串包含'\n'。 | ||
+ | |||
+ | 如果到了文件尾部,再次读就读到一个空字符串。 | ||
+ | |||
+ | ====练习==== | ||
+ | 保存文件c:\abc.txt,打开文件一次读一行字符,读取全部 | ||
+ | |||
+ | <nowiki> | ||
+ | def writeFile(): | ||
+ | fobj=open("c:\\abc.txt","wt") | ||
+ | fobj.write("abc\nxyz") | ||
+ | fobj.close() | ||
+ | |||
+ | def readFile(): | ||
+ | fobj=open("c:\\abc.txt","rt") | ||
+ | goon=1 | ||
+ | st="" | ||
+ | while goon==1: | ||
+ | s=fobj.readline() | ||
+ | if s!="": | ||
+ | st=st+s | ||
+ | else: | ||
+ | goon=0 | ||
+ | fobj.close() | ||
+ | print(st) | ||
+ | |||
+ | try: | ||
+ | writeFile() | ||
+ | readFile() | ||
+ | except Exception as err: | ||
+ | print(err) | ||
+ | |||
+ | </nowiki> | ||
===f.readlines()=== | ===f.readlines()=== | ||
+ | 如果要从文件中读取所有行,那么: | ||
+ | |||
+ | 文件对象.readlines() | ||
+ | |||
+ | 规则: | ||
+ | |||
+ | *它返回所有的行字符串,每行是用"\n"分开的,而且一行的结尾如果是"\n"则包含"\n"。 | ||
+ | *一般再次使用for循环从readlines()中提取每一行。 | ||
+ | |||
f.readlines()也是一次性读入文件的函数,其结果是一个列表,每个元素是文件的一行。 | f.readlines()也是一次性读入文件的函数,其结果是一个列表,每个元素是文件的一行。 | ||
第111行: | 第337行: | ||
fr.close()</nowiki> | fr.close()</nowiki> | ||
− | === | + | ====练习==== |
− | + | 读出students.txt文件学生信息的关键代码如下: | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | <nowiki>f=open("student.txt","rt") | |
+ | while True: | ||
+ | name=f.readline().strip("\n") | ||
+ | if name=="": | ||
+ | break | ||
+ | gender= f.readline().strip("\n") | ||
+ | age=float(f.readline().strip("\n"))</nowiki> | ||
− | |||
− | |||
− | |||
− | |||
===f.write()=== | ===f.write()=== | ||
第163行: | 第381行: | ||
print(line) | print(line) | ||
fp.close()</nowiki> | fp.close()</nowiki> | ||
+ | |||
+ | ===f.tell()=== | ||
+ | 使用tell函数获取当前文件指针的位置,方法是: | ||
+ | |||
+ | 文件对象.tell() | ||
+ | |||
+ | 它返回一个整数。 | ||
+ | |||
+ | 在程序看来,文件就是由一连串的字节组成的字节流,文件的每个字节都有一个位置编号,一个有n个字节的文件字节编号依次为0、1、2、……、n-1号,在第n字节的后面有一个文件结束标志EOF (End Of File),如图为文件的模型,其中标明了文件字节值,文件位置编号以及文件指针的关系,该文件有6个字节,它们是0x41、0x42、0x43、0x41、0x42、0x61,指针目前指向第2字节,EOF是文件尾。 | ||
+ | |||
+ | [[文件:python2022122901.png|600px]] | ||
+ | |||
+ | 如字节流有n个字节,p是指针的位置(0<=p<=n-1),那么读写的规则如下: | ||
+ | |||
+ | *0<=p<=n-1时,指针指向一个文件字节,可以读出该字节,读完后指针会自动指向下一个字节,既p会自动加1;若p指向EOF的位置,则不能读出任何文件字节,EOF通常是循环读文件的循环结束条件。 | ||
+ | |||
+ | *0<=p<=n-1时,指针指向一个文件字节,可以写入一个新的字节,新的字节将覆盖旧的字节,之后指针会自动指向下一个字节,既p会自动加1;若p指向EOF的位置,则新写入的字节会变成第n+1个字节,EOF向后移动一个位置,在字节流的末尾写入会加长文件字节流。 | ||
+ | |||
+ | <nowiki> | ||
+ | s = '新年都未有芳华,二月初惊见草芽。\n白雪却嫌春色晚。故穿庭树作飞花。\n' | ||
+ | fw = open('D:/sample.txt',"wt",encoding="utf-8") | ||
+ | fw.write(s) | ||
+ | print(fw.tell()) | ||
+ | fw.close() | ||
+ | |||
+ | |||
+ | #以文本形式读文件 | ||
+ | fr =open('D:/sample.txt',"rt",encoding="utf-8") | ||
+ | print(fr.tell()) | ||
+ | print(fr.readline()) | ||
+ | print(fr.tell()) | ||
+ | print(fr.readline()) | ||
+ | print(fr.tell()) | ||
+ | fr.close()</nowiki> | ||
+ | |||
+ | ===f.seek()=== | ||
+ | 当从文件中读取内容后,读取指针将向前进,可以用seek()方法将读取指针移动到文件开头 | ||
+ | |||
+ | Python中使用feek函数来移动文件指针,方法是: | ||
+ | |||
+ | 文件对象.seek(offset[,whence]) | ||
+ | |||
+ | *offset -- 开始的偏移量,也就是代表需要移动偏移的字节数 | ||
+ | *whence:可选,默认值为 0。给offset参数一个定义,表示要从哪个位置开始偏移;0代表从文件开头开始算起,1代表从当前位置开始算起,2代表从文件末尾算起。 | ||
+ | |||
+ | 注“”文件如果按"wt+"或者"rt+"的模式打开,那么文件指针可以随意调整,可以随意对文件进行读写。 | ||
+ | |||
+ | <nowiki>#写文件 | ||
+ | s = '新年都未有芳华,二月初惊见草芽。白雪却嫌春色晚。故穿庭树作飞花。' | ||
+ | fw = open('D:/sample.txt',"wt") | ||
+ | fw.write(s) | ||
+ | fw.close() | ||
+ | |||
+ | #以文本形式读文件 | ||
+ | fr =open('D:/sample.txt',"rt") | ||
+ | s=fr.read() | ||
+ | |||
+ | print(s) | ||
+ | |||
+ | fr.seek(0) | ||
+ | |||
+ | s=fr.read() | ||
+ | print(s) | ||
+ | fr.close()</nowiki> | ||
+ | |||
+ | ==综合案例:文件读写== | ||
+ | 以下案例将以上所有函数都用上了: | ||
+ | |||
+ | <nowiki> | ||
+ | def myinput( ):#接受用户输入 | ||
+ | s =input("请输入姓名,性别 年龄,以空格隔开")#例:张三 男 20 | ||
+ | info = [ ] | ||
+ | info = s.split( )#分割字符串 | ||
+ | return info | ||
+ | |||
+ | def write(info):#定义函数,写文件 | ||
+ | try:#加入异常处理语句 | ||
+ | with open(r"d:/test.txt","wt",encoding="utf-8") as fw:#用上下文管理语句with 读写文件 | ||
+ | fw.write(info[0]+"\n")#写入内容 | ||
+ | fw.write(info[1]+"\n") | ||
+ | fw.write(info[2]+"\n") | ||
+ | #print(fw.tell())#告诉文件当前指针的位置 | ||
+ | #fw.writelines(info)#直接将列表类型的各个元素连接起来,写入文件。 | ||
+ | #print(fw.tell())#告诉文件当前指针的位置 | ||
+ | |||
+ | except Exception as e: | ||
+ | print(e) | ||
+ | def read():#定义函数,读文件 | ||
+ | try: | ||
+ | with open(r"d:/test.txt","rt",encoding="utf-8") as fr:#以文本读的方式打开文件 | ||
+ | #result = fr.read(7)#一次性地读取内容, | ||
+ | #result = fr.readline()#读取一行内容 | ||
+ | result = fr.readlines()#读取多行内容 | ||
+ | print("第1次读取文件内容:") | ||
+ | print(result) | ||
+ | print("文件指针重新寻址后,第2次读取文件内容:") | ||
+ | fr.seek(0)#这里的0 代表文件指针距离文件开始位置的偏移,可以设成其他数值 | ||
+ | result = fr.readlines()#读取多行内容 | ||
+ | print(result) | ||
+ | ''' | ||
+ | #逐行的遍历文件 | ||
+ | result = [ ] | ||
+ | for line in fr: | ||
+ | result.append(line.strip()) | ||
+ | ''' | ||
+ | |||
+ | return result | ||
+ | except Exception as e: | ||
+ | print(e) | ||
+ | return "error:",+str(e) | ||
+ | |||
+ | |||
+ | |||
+ | if __name__=="__main__": | ||
+ | info = myinput()#用户输入 | ||
+ | print("打印用户输入的数据:") | ||
+ | print(info)#打印用户输入的数据 | ||
+ | print("将用户输入的内容写入文件:") | ||
+ | write(info)#将用户输入的内容写入文件 | ||
+ | print("从文件中读取内容:") | ||
+ | read( )#从文件中读取内容</nowiki> |
2023年5月8日 (一) 02:01的最新版本
文件的使用
文件的打开和关闭
open函数的格式
open(file, mode='r', buffering=-1, encoding=None, errors=None,newline=None, closefd=True, opener=None)
- file参数指定了被打开的文件路径。
- mode参数指定了打开文件后的处理方式。
- buffering参数指定了读写文件的缓存模式。0表示不缓存,1表示缓存,如大于1则表示缓冲区的大小。默认值是缓存模式。
- encoding参数指定对文本进行编码和解码的方式,只适用于文本模式,可以使用Python支持的任何格式,如GBK、utf8、CP936等等。
文件打开模式
文件打开模式:
python文件打开模式:
- b模式:以二进制模式打开文件
- t模式:以文本模式打开文件
- r模式:以读模式打开文件,如文件不存在则抛出异常
- w模式:以写模式打开文件,如果文件已存在,则清空原有内容
- x模式:以写模式打开文件,如果文件已存在,则抛出异常
- a模式:以追加写模式打开文件,不覆盖文件原有内容
- +模式:以读、写模式打开文件,既能读,又能写。
- 文件写模式:w 代表清空文件原有内容,a 代表在文件原有内容上追加,x 代表创建新文件,如果文件已存在,则抛出异常
使用方法
- 如果执行正常,open()函数返回1个文件对象,通过该文件对象可以对文件进行读写操作。如果指定文件不存在、访问权限不够、磁盘空间不足或其他原因导致创建文件对象失败则抛出异常。
f1 = open( 'file1.txt', 'r' ) # 以读模式打开文件 f2 = open( 'file2.txt', 'w') # 以写模式打开文件
- 当对文件内容操作完以后,一定要关闭文件对象,这样才能保证所做的任何修改都确实被保存到文件中。
f1.close()
例题:
s = "队伍名\n队长:XXX\n队员:XXX XXX XXX\n" fw = open(r"d:\sample123.txt","w") fw.write(s) fw.close() fr = open(r"d:\sample123.txt","r") print(fr.read()) fr.close()
注:写路径时,前面要加上字母r ,表示按照字符的原义去理解路径中的字符
文件操作属于I/O操作,I/O操作中可能因为I/O设备的原因有时操作不正确,因此I/O操作一般建议使用try语句捕获有可能发生的错误。
try: f=open(“c:\\xyz.txt”,“rt”) f.close() except: print("文件打开失败")
练习
输入若干个学生的姓名Name、性别Gender、年龄Age,把它存储到文件students.txt中,每个数据项占一行。
def write(info):#定义函数,写文件 try:#加入异常处理语句 fw = open(r"d:/test.txt","wt")#以文本写的方式打开文件 fw.write(info[0]+"\n")#写入内容 fw.write(info[1]+"\n") fw.write(info[2]+"\n") fw.close() except Exception as e: print(e) def myinput( ):#接受用户输入 s =input("请输入姓名,性别 年龄,以空格隔开") info = [ ] info = s.split( )#分割字符串 return info def read():#定义函数,读文件 try: fr = open(r"d:/test.txt","rt")#以文本读的方式打开文件 result = fr.read() return result except Exception as e: print(e) return "error:",+str(e) if __name__=="__main__": info = myinput() print(info) write(info) r = read( ) print(r)
文件的类型
文件包括文本文件和二进制文件两种类型。
文本文件一般由单一特定编码的字符串组成,如如一个txt格式的文本文件。
二进制文件直接由比特0和皮特一组成,没有统一的字符编码。二进制文件由于没有统一的字符编码,只能当做字节流,而不能看作是字符串。
当用二进制方法写文件时,必须将字符串用encode函数编一下码
例题:
#以文本形式写文件 s = '新年都未有芳华,二月初惊见草芽。\n白雪却嫌春色晚。故穿庭树作飞花。\n' fw = open('sample.txt',"wt") fw.write(s) fw.close() #以文本形式读文件 fr =open('sample.txt',"rt") print(fr.read()) fr.close() #以二进制形式写文件 fw = open('sample.txt',"wb") fw.write(s.encode("gbk")) fw.close() #以二进制形式读文件 fr =open('sample.txt',"rb") print(fr.read()) fr.close() #以文本形式读文件 fr =open('sample.txt',"rt") print(fr.read()) fr.close()
文件读写结束时,一定要加入fr.close() 来关闭输入输出流。
文件的遍历
文本文件可以看作是由行组成的组合类型,因此也可以使用遍历循环逐行的遍历文件。
s = '新年都未有芳华,\n二月初惊见草芽。\n白雪却嫌春色晚。\n故穿庭树作飞花。' fw = open('sample.txt',"wt") fw.write(s) fw.close() fp =open('sample.txt',"rt") #假设文件采用CP936编码 for line in fp: #文件对象可以直接迭代 print(line) fp.close()
可以用for循环来逐行读入文件数据
文件的编码
GBK编码
是指中国的中文字符,其它它包含了简体中文与繁体中文字符,另外还有一种字符“gb2312”,这种字符仅能存储简体中文字符。
GBK中一个英文字符占一个字节(ASCII),一个汉字两字节
UTF-8编码
它是一种全国家通过的一种编码,如果你的网站涉及到多个国家的语言,那么建议你选择UTF-8编码。
UTF-8中一个英文字符占一个字节(ASCII),一个汉字通常占3字节
保存包括中文在内的多语言文件,一般用UTF-8编码较多
在中文Windows系统中如果我们不指定文本文件的编码,那么它采用系统默认的GBK编码。
如果我们想改变默认编码方式,在open函数中添加参数:encoding="utf-8
如: fobj=open("c:\\abc.txt","wt",encoding="utf-8")
用utf-8编码写文件,稍后读的时候也需用utf-8编码来读,否则会报错。
例6-3-1: GBK编码
fobj=open("c:\\abc.txt","wt") fobj.write("abc我们") fobj.close()
执行后abc.txt文件是7个字节,分别是:
0x61 0x62 0x63 0xce 0xd2 0xc3 0xc7
其中前3个是abc字符,0xce,0xd2这2个字节是汉字"我"的内码,0xc3,0xc7这2个字节是汉字"们"的内码。
指定文件编码
如果我们不使用默认的编码,可以在open函数中用encoding参数指定编码。
fobj=open("c:\\abc.txt","wt",encoding="utf-8") fobj.write("abc我们") fobj.close()
执行后abc.txt文件是9个字节,分别是:
0x61 0x62 0x63 0xe6 0x88 0x91 0xe4 0xbb 0xac
其中前3个是abc字符,0xe6, 0x88, 0x91这3个字节是汉字"我"的UTF-8编码,0xe4,0xbb ,0xac这3个字节是汉字"们"的UTF-8编码。
练习
用UTF-8编码存储文本文件,再用相同编码读取文件。
思考:如果用其他的编码方式读取,会出现什么结果?
s="队名:精神小伙 队员:张三 李四 王五\n \t" fw = open(r"C:\Users\maxin\Documents\teaching\2023Python程序设计\1.txt",'wb')#以二进制模式写 fw.write(s.encode("utf-8")) fw.close()#这句不能忽略 fr = open(r"C:\Users\maxin\Documents\teaching\2023Python程序设计\1.txt",'rb')#以二进制模式读 print(fr.read( )) fr.close()#这句不能忽略 fw = open(r"C:\Users\maxin\Documents\teaching\2023Python程序设计\1.txt",'wt',)#以文本模式写 fw.write(s) fw.close()#这句不能忽略 fr = open(r"C:\Users\maxin\Documents\teaching\2023Python程序设计\1.txt",'rt')#以文本模式读 print(fr.read( )) fr.close()#这句不能忽略 fw = open(r"C:\Users\maxin\Documents\teaching\2023Python程序设计\1.txt",'at')#以文本模式追加写 fw.write(s) fw.close()#这句不能忽略 fw = open(r"C:\Users\maxin\Documents\teaching\2023Python程序设计\1.txt",'a')#省略t字母 fw.write(s) fw.close()#这句不能忽略 fr = open(r"C:\Users\maxin\Documents\teaching\2023Python程序设计\1.txt",'r+')#既能读,又能写 print(fr.read( )) fr.close()#这句不能忽略
上下文管理语句with
在实际开发中,读写文件应优先考虑使用上下文管理语句with,关键字with可以自动管理资源,不论因为什么原因(哪怕是代码引发了异常)跳出with块,总能保证文件被正确关闭,并且可以在代码块执行完毕后自动还原进入该代码块时的上下文,常用于文件操作、数据库连接、网络连接、多线程与多进程同步时的锁对象管理等场合。
with open(filename, mode, encoding) as fp: #这里写通过文件对象fp读写文件内容的语句
- 上下文管理语句with还支持下面的用法:
with open('test.txt', 'r') as src, open('test_new.txt', 'w') as dst: dst.write(src.read())
所以,上面那个例子用上下文语句可以这么写:
s = 'Hello world\n文本文件的读取方法\n文本文件的写入方法\n' with open('sample.txt',"w") as fw: fw.write(s) with open('sample.txt',"r") as fr: print(fr.read())
可以用上下文管理语句with 来简写文件输入输出
文件的读写函数
f.read()
如果文件不大,可以一次性将文件内容读入,保存到程序内部变量当中,f.read()是最常用的一次性读文件的函数。
函数调用的形式为:
文件对象.read() 文件对象.read(n)
- 如果不指定要读取的字符数n,使用read()读,则读到整个文件的内容;
- 如果使用read(n)指定要读取的字符数,那么就按要求读取n个字符;
- 如果要读n个字符,而文件没有那么多字符,那么就读取所有文件内容。
- 如果文件指针已经到了文件的尾部,再读就返回一个空串。
#写文件 s = '新年都未有芳华,二月初惊见草芽。白雪却嫌春色晚。故穿庭树作飞花。' fw = open('D:/sample.txt',"wt") fw.write(s) fw.close() #以文本形式读文件 fr =open('D:/sample.txt',"rt") print(fr.read()) fr.close()
练习
例6-4-3:保存文件c:\abc.txt,打开文件一次读一个字符,读取全部
readline()
如果要从文件中读取一行,那么可以使用readline()
规则:
它返回一行字符串。readline()的规则是在文件中连续读取字符组成字符串,一直读到'\n'字符或者读到文件尾部为止。
注意如果读到'\n',那么返回的字符串包含'\n'。
如果到了文件尾部,再次读就读到一个空字符串。
练习
保存文件c:\abc.txt,打开文件一次读一行字符,读取全部
def writeFile(): fobj=open("c:\\abc.txt","wt") fobj.write("abc\nxyz") fobj.close() def readFile(): fobj=open("c:\\abc.txt","rt") goon=1 st="" while goon==1: s=fobj.readline() if s!="": st=st+s else: goon=0 fobj.close() print(st) try: writeFile() readFile() except Exception as err: print(err)
f.readlines()
如果要从文件中读取所有行,那么:
文件对象.readlines()
规则:
- 它返回所有的行字符串,每行是用"\n"分开的,而且一行的结尾如果是"\n"则包含"\n"。
- 一般再次使用for循环从readlines()中提取每一行。
f.readlines()也是一次性读入文件的函数,其结果是一个列表,每个元素是文件的一行。
fr =open('D:/sample.txt',"rt") print(fr.readlines()) fr.close()
练习
读出students.txt文件学生信息的关键代码如下:
f=open("student.txt","rt") while True: name=f.readline().strip("\n") if name=="": break gender= f.readline().strip("\n") age=float(f.readline().strip("\n"))
f.write()
f.write()向文件写入字符串,每次写入后,将会记录一个写入指针。
f = open("D:/test.txt","w") f.write("新年都未有芳华。\n") f.write("2月初惊见草芽。\n") f.write("白雪却嫌春色晚。\n") f.write("故穿庭树作飞花。\n") f.close() fp =open('D:/test.txt',"rt") for line in fp: #文件对象可以直接迭代 print(line) fp.close()
f.writelines()
f.writelines()直接将列表类型的各个元素连接起来,写入文件。
f = open("D:/test.txt","w") #f.write("新年都未有芳华。\n") #f.write("2月初惊见草芽。\n") #f.write("白雪却嫌春色晚。\n") #f.write("故穿庭树作飞花。\n") ls = ['新年都未有芳华,\n二月初惊见草芽。\n白雪却嫌春色晚。\n故穿庭树作飞花。\n'] f.writelines(ls) f.close() fp =open('D:/test.txt',"rt") for line in fp: #文件对象可以直接迭代 print(line) fp.close()
f.tell()
使用tell函数获取当前文件指针的位置,方法是:
文件对象.tell()
它返回一个整数。
在程序看来,文件就是由一连串的字节组成的字节流,文件的每个字节都有一个位置编号,一个有n个字节的文件字节编号依次为0、1、2、……、n-1号,在第n字节的后面有一个文件结束标志EOF (End Of File),如图为文件的模型,其中标明了文件字节值,文件位置编号以及文件指针的关系,该文件有6个字节,它们是0x41、0x42、0x43、0x41、0x42、0x61,指针目前指向第2字节,EOF是文件尾。
如字节流有n个字节,p是指针的位置(0<=p<=n-1),那么读写的规则如下:
- 0<=p<=n-1时,指针指向一个文件字节,可以读出该字节,读完后指针会自动指向下一个字节,既p会自动加1;若p指向EOF的位置,则不能读出任何文件字节,EOF通常是循环读文件的循环结束条件。
- 0<=p<=n-1时,指针指向一个文件字节,可以写入一个新的字节,新的字节将覆盖旧的字节,之后指针会自动指向下一个字节,既p会自动加1;若p指向EOF的位置,则新写入的字节会变成第n+1个字节,EOF向后移动一个位置,在字节流的末尾写入会加长文件字节流。
s = '新年都未有芳华,二月初惊见草芽。\n白雪却嫌春色晚。故穿庭树作飞花。\n' fw = open('D:/sample.txt',"wt",encoding="utf-8") fw.write(s) print(fw.tell()) fw.close() #以文本形式读文件 fr =open('D:/sample.txt',"rt",encoding="utf-8") print(fr.tell()) print(fr.readline()) print(fr.tell()) print(fr.readline()) print(fr.tell()) fr.close()
f.seek()
当从文件中读取内容后,读取指针将向前进,可以用seek()方法将读取指针移动到文件开头
Python中使用feek函数来移动文件指针,方法是:
文件对象.seek(offset[,whence])
- offset -- 开始的偏移量,也就是代表需要移动偏移的字节数
- whence:可选,默认值为 0。给offset参数一个定义,表示要从哪个位置开始偏移;0代表从文件开头开始算起,1代表从当前位置开始算起,2代表从文件末尾算起。
注“”文件如果按"wt+"或者"rt+"的模式打开,那么文件指针可以随意调整,可以随意对文件进行读写。
#写文件 s = '新年都未有芳华,二月初惊见草芽。白雪却嫌春色晚。故穿庭树作飞花。' fw = open('D:/sample.txt',"wt") fw.write(s) fw.close() #以文本形式读文件 fr =open('D:/sample.txt',"rt") s=fr.read() print(s) fr.seek(0) s=fr.read() print(s) fr.close()
综合案例:文件读写
以下案例将以上所有函数都用上了:
def myinput( ):#接受用户输入 s =input("请输入姓名,性别 年龄,以空格隔开")#例:张三 男 20 info = [ ] info = s.split( )#分割字符串 return info def write(info):#定义函数,写文件 try:#加入异常处理语句 with open(r"d:/test.txt","wt",encoding="utf-8") as fw:#用上下文管理语句with 读写文件 fw.write(info[0]+"\n")#写入内容 fw.write(info[1]+"\n") fw.write(info[2]+"\n") #print(fw.tell())#告诉文件当前指针的位置 #fw.writelines(info)#直接将列表类型的各个元素连接起来,写入文件。 #print(fw.tell())#告诉文件当前指针的位置 except Exception as e: print(e) def read():#定义函数,读文件 try: with open(r"d:/test.txt","rt",encoding="utf-8") as fr:#以文本读的方式打开文件 #result = fr.read(7)#一次性地读取内容, #result = fr.readline()#读取一行内容 result = fr.readlines()#读取多行内容 print("第1次读取文件内容:") print(result) print("文件指针重新寻址后,第2次读取文件内容:") fr.seek(0)#这里的0 代表文件指针距离文件开始位置的偏移,可以设成其他数值 result = fr.readlines()#读取多行内容 print(result) ''' #逐行的遍历文件 result = [ ] for line in fr: result.append(line.strip()) ''' return result except Exception as e: print(e) return "error:",+str(e) if __name__=="__main__": info = myinput()#用户输入 print("打印用户输入的数据:") print(info)#打印用户输入的数据 print("将用户输入的内容写入文件:") write(info)#将用户输入的内容写入文件 print("从文件中读取内容:") read( )#从文件中读取内容