Python文件的使用
文件的使用
文件的打开和关闭
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( )#从文件中读取内容