Python编程之文件操作
文件操作流程
打开文件,得到文件句柄并赋值给一个变量
通过句柄对文件进行操作
关闭文件
每次文件打开、读取信息时,Python自动记录所达到的位置,好比一个书签,之后每一次读取都会从上次结束的地方开始,如果要从开始的位置读取,可以将其关闭后打开。
文件操作模式
r :只读模式 (默认)
w :只写模式 (不可读;如果文件不存在,则创建新文件;如果文件存在,则删除原内容
a :追加模式 (不可读;如果文件不存在,则创建新文件;如果文件存在,则在文件末追加内容)
r+ :可读可写,追加形式写入,读取行位置不变
w+ :写读,覆盖形式写入,此时在文件最后,如果需要读取文件,则需要使用seek
a+ :可读可写,追加形式写入,以这个模式打开文件,默认在文件末尾,如果需要读取文件,则需要使用seek
b : 处理二进制文件(FTP发送上传ISO镜像文件,linux可忽略,windows处理二进制文件时需标注),在socket编程中,python3.x以二进制传输,需要encode,python2.x可以通过字符串传输
rb: 二进制形式读取文件,注意此时不能有encoding = "utf-8",会报错ValueError。
wb:
ab:
U:表示在读取时,可以将 自动转换成 (与 r 或 r+ 模式同使用,例如:rU 或 r+U)
文件缓存:写入文件时,可能写入内容还在缓存中,并没有写进硬盘,可以通过flush方法冲刷缓存,写进硬盘中。
with语句:当with代码块执行完毕时,内部会自动关闭并释放文件资源。
python2.7之后,with支持同时对多个文件的上下文管理。
文件读写操作
#*************************读************************ #默认读取,则整个文件以字符串形式返回 f = open("file","r",encoding="utf-8") #文件句柄,输出中文时注意文件编码 data = f.read() #读取剩下的所有内容,文件大时不建议使用 data2 = f.read() #此时文件已经读取完,书签在文件末,data2中为空 print(data) print("---------------") print(data2) f.close() #按指定字符数 f = open("file","r",encoding="utf-8") print(f.read(1)) print(f.read(4)) f.close() 生 当作人杰 #按行读取 f = open("file","r",encoding="utf-8") print(f.readline()) print(f.readline()) f.close() #原文档有回车,所以有一个空行 f = open("file","r",encoding="utf-8") lines = f.readlines() print(lines,len(lines)) f.close() ['生当作人杰 ', '死亦为鬼雄 ', '至今思项羽 ', '不肯过江东'] 4 #for循环迭代 f = open("file","r",encoding="utf-8") for line in f: #一行一行的读,效率比较高 print(line) f.close() #模块自动关闭文件 with open('file','r',encoding="utf-8") as f: print(f.read()) #*****************写******************* text_file = open("write_it.txt","w") #会自动创建一个新文件,原来如果有个这个文件,则会覆盖,慎用 text_file.write("Line 1 ") text_file.write("This is line 2 ") text_file.write("That makes this line 3 ") #将字符串列表写入到文件 text_file = open("write_it.txt","w") lines = ["Line ", "This is line 2 ", "That makes this line 3 "] text_file.writelines(lines) text_file.close()
文件追加与修改操作
#*****************追加******************* f = open("file","a",encoding="utf-8") #在文件后追加信息,注意使用“ ” f.write(" 李清照") f.close() #**********************可读可写模式****************** f = open("file","r+",encoding="utf-8") #文件句柄,输出中文时注意文件编码 data = f.read() #读取剩下的所有内容,文件大时不建议使用 f.write(" 南宋") f.close() #**********************修改文件****************** f = open("file","r",encoding="utf-8") #文件句柄,输出中文时注意文件编码 f_new = open("file.bak","w",encoding="utf-8") for line in f: if "西天的云彩" in line: line = line.replace("西天的云彩","今天的离别") f_new.write(line) f.close() f_new.close() #结论:通过匹配要修改的内容修改,保存在另外一个新建文件中。
二进制文件操作
f = open("file","rb") #文件句柄,输出中文时注意文件编码 print(f.read()) f.close() #b'hello world' f = open("file","wb") #文件句柄,输出中文时注意文件编码 f.write("Hello world ".encode()) f.close()
with语句操作
with open("loginlog.txt","r") as f: for line in f: print(line) #代码块执行完毕后会自动关闭文件 #with打开多个文件 with open("loginlog.txt","r") as f, #python代码规范,一行尽量不要超过80个字符,建议用换行 open("1111","r") as f2: for line in f: print(line)
文件其他操作
#**********文件的其他用法******************** f = open("file","r",encoding="utf-8") print(f.tell()) #tell 返回文件当前位置,按字节计算 date = f.readline() date = f.readline() print(f.tell()) f.seek(15) #seek 移动到文件某个字符位置,一个汉字为3个字节 #seekable 是否可以移动,tty文件不可以 print(f.readline()) print(f.encoding) #encoding 返回文件编码 print(f.fileno()) #fileno 调用操作系统哪个接口 print(f.flush()) #flush 冲刷文件的内部缓存 f.truncate(10) #从头开始截断,原文件只剩下10个字符,不指定参数会清空原文件, f.close()
文件操作问题
#***********************文件操作问题****************** #文件内容: abcdefghijklmno #**************模式:r+************************ f = open("file","r+",encoding="utf-8") print("初始位置:", f.tell()) data2 = f.read(5) print("-------%s-------" % (data2) ) print("读取五个字母之后的位置:", f.tell()) f.write("a") print("写入一个字母之后的位置:", f.tell()) data = f.read(5) print("-------%s-------" % (data) ) print("再次读入五个字母之后的位置:", f.tell()) f.close() 初始位置: 0 -------abcde------- 读取五个字母之后的位置: 5 写入一个字母之后的位置: 19 #追加 -------fghij------- #从第6个位置开始读 再次读入五个字母之后的位置: 19 #结论:读取正常,在文件末尾添加,但是继续读取和tell()返回的值不一致 #问题:如果先写再读,则不是追加,会从文件开始覆盖增加 f = open("file","r+",encoding="utf-8") #文件句柄,输出中文时注意文件编码 f.write("yyy") print("写入字母之后的位置:", f.tell()) data2 = f.read(5) print("-------%s-------" % (data2) ) print("读取字母之后的位置:", f.tell()) f.write("zzz") print("写入字母之后的位置:", f.tell()) data = f.read(5) print("-------%s-------" % (data) ) print("再次读入五个字母之后的位置:", f.tell()) f.close() 写入字母之后的位置: 3 -------defgh------- 读取字母之后的位置: 8 写入字母之后的位置: 17 -------ijkzz------- 再次读入五个字母之后的位置: 17 #修改:加入seek(0,2), f = open("file","r+",encoding="utf-8") #文件句柄,输出中文时注意文件编码 f.seek(0,2) f.write("yyy") print("写入字母之后的位置:", f.tell()) data2 = f.read(5) print("-------%s-------" % (data2) ) print("读取字母之后的位置:", f.tell()) f.write("zzz") print("写入字母之后的位置:", f.tell()) data = f.read(5) print("-------%s-------" % (data) ) print("再次读入五个字母之后的位置:", f.tell()) f.close() #结论:在文件末添加,但是读取会出现异常,需要添加seek(0) #******************模式:w+********************* f = open("file","w+",encoding="utf-8") #文件句柄,输出中文时注意文件编码 print("初始位置:", f.tell()) f.write("abcdefghijk") print("写入字母之后的位置:", f.tell()) data2 = f.read(5) print("-------%s-------" % (data2) ) print("读取字母之后的位置:", f.tell()) f.write("zzz") print("写入一个字母之后的位置:", f.tell()) data = f.read(5) print("-------%s-------" % (data) ) print("再次读入五个字母之后的位置:", f.tell()) f.close() 初始位置: 0 写入字母之后的位置: 11 -------------- 读取字母之后的位置: 11 写入一个字母之后的位置: 14 -------------- 再次读入五个字母之后的位置: 14 #修正:在第一次写入后,加seek(0)情况 初始位置: 0 写入字母之后的位置: 11 当前位置: 0 -------abcde------- 读取字母之后的位置: 5 写入字母之后的位置: 14 -------fghij------- 再次读入五个字母之后的位置: 14 #******************模式:a+**************** f = open("file","a+",encoding="utf-8") print("初始位置:", f.tell()) data2 = f.read(5) print("-------%s-------" % (data2) ) print("读取字母之后的位置:", f.tell()) f.write("zzz") print("写入字母之后的位置:", f.tell()) data = f.read(5) print("-------%s-------" % (data) ) print("再次读入五个字母之后的位置:", f.tell()) f.close() -------------- 读取字母之后的位置: 11 写入字母之后的位置: 14 -------------- 再次读入五个字母之后的位置: 14 #结论:在文件后追加,读取文件有问题,没有输出 #修改:在第一次读取前添加seek(0) -------abcde------- 读取字母之后的位置: 5 写入字母之后的位置: 17 #追加 -------fghij------- #从第6个位置开始读 再次读入五个字母之后的位置: 17 #结论: 添加seek(0)可以解决读取的问题,但是tell()返回位置和继续读取位置不一样