本文主要记录Python中的文件的常用操作
1.文件操作的流程
1)打开文件,得到文件句柄并赋值给一个变量
2)通过句柄对文件进行操作
3)操作完成,关闭文件
2.打开文件的常用模式
有以下2个示例文件:
# hello_gbk.txt文件为GBK编码,hello_utf8.txt文件为utf-8编码
Somehow, it seems the love I knew was always the most destructive kind 不知为何,我经历的爱情总是最具毁灭性的的那种 Yesterday when I was young 昨日当我年少轻狂 The taste of life was sweet 生命的滋味是甜的 As rain upon my tongue 就如舌尖上的雨露 I teased at life as if it were a foolish game 我戏弄生命 视其为愚蠢的游戏
2.1.一般模式
"r"ģʽ
#"r"只读模式,是默认模式,默认编码是gbk,不可写
# print(f.read(10)) # 默认读全文,可以按照指定字符数量读文件内容 # print(f.readline(10)) # 默认读取一行,遇到\r或者\n为止,适合读小文件,也可以按照指定字符数量读文件内容 # print(f.readlines(1)) # 默认读取全文转换为带\n的列表,括号中指定数字,读取第一行 # print(f.readlines()[3]) # 可以用这种方式读取出某4行
实例1:文件读取
f = open(file='hello_gbk.txt',mode='r',encoding='gbk') # 标准完整格式,文件名可以加绝对路径 # f = open('hello_gbk.txt') # 最简单的写法 # f = open('hello_gbk.txt',encoding='gbk') # 简写2,最后的encoding必须写上 print(f.readline()) # 读一行内容 print('分隔线'.center(50,'-')) data = f.read() # 读取剩下的所有内容,文件大时不要用 print(data) #打印文件 f.close() #关闭文件
注解:
mode='r' encoding='utf-8' #表示 只读 硬盘上的0101按照utf-8的规则去‘断句’,再将断句后的每一段0101转换成Unicode的01010,Unicode对照表中0101和字符的对应关系。
mode='rb' # 以什么形式存的就以什么形式读 ,二进制打开,给机器看的,用于视频,图片,网络传输
实例2:读前3行内容--->思路:使用循环
# 简单想法:尝试以下3种方式
# 方法1: f = open(file='hello_gbk.txt',mode='r',encoding='gbk') for i in range(3): print(f.readline().strip()) # 方法2: f = open(file='hello_gbk.txt',mode='r',encoding='gbk') for index,line in enumerate(f.readlines()): if index == 5: print("--------") exit() print(line.strip()) # 注意:以上2中方法在读大文件的时候可能会把内存撑爆,所以readline()的方式不能用于读大文件 # 方法3:优化后,读一行删一行,内存中只保留一行内容,如下: f = open(file='hello_gbk.txt',mode='r',encoding='gbk') count = 0 for line in f: # 不是列表了,变成了文件迭代器 if count == 5: print("----------") count += 1 exit() print(line.strip()) count += 1 # 这种方法3是读取文件的最优方法
# "w"创建文件,不可读文件,如果有同名文件则相当于清空数据,重新写入,所以要慎用
实例1:创建文件
f = open("hello2.txt",'w') # 不指定编码,默认创建gbk格式的文件 f.write("hello2") f.close() f = open("hello2.txt",'w',encoding='utf-8') # 如果要创建指定编码格式的文件,需要加“encoding=”字段 f.write("hello2") f.close()
注意:在pycharm中写的内容用的是unicode,但在保存成txt文件时会自动转码为GBK的
# "a"追加,但不可读文件,使用a可以直接打开文件,然后直接追加内容
实例1:追加内容
f = open("hello2.txt",'a',encoding='gbk') f.write("\n我是追加的内容1") # 写入的内容需要和原文件编码相同,否则会出现部分乱码,\n用于换行 f.close()
2.2.混合读写模式
# "r+"读写模式。可读,可写,可追加。偶尔用
实例1:追加写入文件内容
f = open("hello2.txt",'r+',encoding='gbk') # 使用"r+",不管怎样移动光标,文字都会追加到文件最后 data = f.read() # 必须先读到内存中,然后追加,最后写回文件中 print(data) f.write("\n再写点东西") f.close()
"w+"ģʽ
# "w+",写读模式,会先创建一个文件再写入,也就是清空文件内容,慎用(不用)
实例1:
f = open("hello2.txt",'w+',encoding='gbk') data = f.read() print(data) # 先创建空文件,所以读不出内容,也就无打印 f.write("\n我还要写点东西") f.close()
# "a+",同a,追加模式,可读(可用)
2.3.二进制模式,"b"表示处理二进制文件
二进制"rb"模式
#1)网络传输:FTP发送上传ISO镜像文件,linux可忽略,windows处理二进制文件时需标注
#2)音视频文件读写
实例1:
f = open("hello3.txt",'rb') # 使用二进制写模式rb打开文件,不需要使用encoding='gbk' print(f.read()) # 打印的是二进制额bytes数据 f.close()
# 实例2:调用chardet模块(需要单独安装),推断文件的编码格式
pip3 install chardet
import chardet result = chardet.detect(open(file='hello3.txt',mode='rb').read()) print(result) --->{'encoding': 'GB2312', 'confidence': 0.99, 'language': 'Chinese'}
# 用二进制创建文件,音视频,图片或者其他任何数据等,可以直接传输,可以手动编码
实例1:
f = open("hello3.txt",'wb') # 使用二进制写模式wb打开文件,不需要使用encoding='gbk' f.write("hello3中国你好,二进制写一句".encode('gbk')) # 使用二进制写入“hello3”,需要转码,否则报错,可以指定GBK,utf-8等进行编码 f.close()
二进制"ab"模式
# 二进制方式追加文件内容
实例1:
f = open("hello3.txt",'ab') # 使用二进制追加模式ab打开,进行追加,不需要使用encoding='gbk' f.write("\n我是用二进制追加的内容".encode('gbk')) # 如果使用二进制方式ab写文件,需要转码,否则报错 f.close()
2.4.兼容读写模式
# 用于windows和linux的兼容
"U"表示在读取时,可以将 \r \n \r\n自动转换成 \n (与 r 或 r+ 模式同使用)
rU r+U
3.文件的其他操作方法:
# f.flush()将内存中的内容手动刷新到硬盘中,需要到windows的客户端里测试刷新效果--------------------------------
f = open("hello3.txt", 'w') f.write("\ntest flush") f.flush() f.close()
# 拓展:进度条
import sys,time for i in range(50): sys.stdout.write("#") # 默认不换行 sys.stdout.flush() time.sleep(0.5)
3.2.移动光标
# f.tell()返回当前操作的文件的光标位置
# f.seek()移动光标到指定位置
# f.read()是按照字符读文件,f.tell()和.seek()是按照字节读文件
# 拓展:不同的字符编码中,每个字符所占用的字节长度不一样,所以在不同的编码中同一个字的seek就不同 1)ASCII码一个字符默认占1个字节,8位,不能存中文,所以出了Unicode 2)GBK中:一个中文字符占用2个字节,1个英文字符占用1个字节 3)utf-8是一个汉字占用3个字节,所有的英文用ASCII码存,一个字符默认占1个字节,8位 4)unicode中:一个中文字符占2个字节,16位,
# 实例:不同字符编码下的光标位置
使用GBK
f = open("hello_gbk.txt","r",encoding="gbk") f.seek(13) # 光标移动13个字节,在GBK下中文占2个字节,英文占1个字节 print(f.read(10)) # 读10个字符,不区分中英文 print(f.tell()) # 回车\n也计算了一个字节 f.close()
使用utf-8
f = open("hello_utf8.txt","r",encoding="utf8") f.seek(13) # 光标移动13个字节,在utf-8下中文占3个字节,英文占1个字节,注意文件开头占3个字节 print(f.read(10)) # 可以看到与上面的结果不相同 print(f.tell()) f.close()
3.3.截取文件内容
# .truncate()从第n个字符截断(去掉)文件内容
1)指定长度:截取文件开头到指定长度位置的字符内容
2)不指定长度:截取文件开头到光标所在位置的字符内容
# 实例1:截取开头10个字符的内容
# 方法1:截取开头到指定长度的字符,简单高效 f = open("hello3.txt", 'r+', encoding='gbk') # 使用"r+"或"a" f.seek(100) # 与光标在哪无关 print(f.tell()) f.truncate(10) f.close() # 方法2:移动光标,从开头截取到光标位置 f = open("hello3.txt",'r+',encoding='gbk') # 使用"r+"或"a" f.seek(10) print(f.tell()) f.truncate() f.close()
3.4.其他一些简单的方法:
f.fileno() 用于返回文件句柄在内核中的索引值,在做IO多路复用时可以用到,一般用不到 f.isatty() 判断是否是个终端文件 f.seekable() 判断文件是否可进行seek操作 f.readable() 判断文件是否可读,w不可读 f.writable() 判断文件是否可写
f = open("hello_gbk.txt",'r+',encoding='utf-8') # 使用"r+" print(f) print(f.encoding) # 打印文件的编码格式,注意后面不加括号 print(f.name) # 打印文件的名字 print(f.buffer) print(f.errors)
4.with语句,自动关闭文件
# 为了避免打开文件后忘记关闭,可以通过with方法打开文件
with open("hello2.txt",'r',encoding='gbk') as f: print(f.read())
# 如果一次打开较多文件,建议换行书写代码
with open("hello2.txt") as f1 ,\ open("hello3.txt") as f2: for i1 in f1: print(i1.strip()) for i2 in f2: print(i2.strip())
5.修改文件内容的一般方法:
1)类似vim这种,将修改的文件内容加载到内存中,修改完保存到源文件中
内存中的内容不存在写数据就覆盖的问题会自动移位
但是如果打开大文件,内存可能不够,或者系统变慢
2)读到缓存文件中逐行读写,修改完使用临时文件覆盖原文件
import os f_name = "hello3.txt" f_new_name = "%s.new" %(f_name) old_str = "[[改了又改]]" # find_str = sys.argv[1] new_str = "[想改就改,改的响亮]" # replace_str = sys.argv[2] f = open(f_name,'r',encoding="gbk") f_new = open(f_new_name,'w',encoding="gbk") for line in f: if old_str in line: new_line = line.replace(old_str,new_str) # new_line = line.replace(find_str,replace_str) else: new_line = line f_new.write(new_line) f.close() f_new.close() os.replace(f_new_name,f_name) # os.rename(f_new_name,f_name) # mac,linux
完毕,呵呵呵呵