文件处理流程
- 打开文件,得到文件句柄并赋值给一个变量
- 通过句柄对文件进行操作
- 关闭文件
1 f = open(file='D:/工作日常/text.txt',mode='r',encoding='utf-8')
打开模式:
文件的打开模式 mode
r 只读模式,文件不存在时会报错。
w 写入模式,文件存在会清空之前的内容,文件不存在则会新建文件。
x 写入模式,文件存在会报错,文件不存在则会新建文件。
a 追加写入模式,不清空之前的文件,直接将写入的内容添加到后面。
b 以二进制模式读写文件,wb,rb,ab。
+ 可读写模式,r+,w+,x+,a+,这几种模式还遵循了r,w,x,a的基本原则。
文件的encoding
根据文件的encoding格式打开文件,windows默认GBK,MAC和linux默认UTF-8
当使用wb,rb,ab模式读取文件时,不用填写encoding
# 以二进制形式打开文件不需要编码 f = open(r"text.txt", "wb") f.write("路飞 ".encode()) # 写入utf-8二进制字节码 f.write("路飞 Yifei Qiao]".encode()) f.close()
如果文件encoding格式为utf-8,打开encoding格式为GBK则读取文件会报错
检查文件编码
import chardet """ 安装模块pip install chardet """ # 检测文件编码 要以二进制形式读取 result = chardet.detect(open(r"text.txt", "rb").read()) print(result) # {'encoding': 'utf-8', 'confidence': 0.938125, 'language': ''}
基本操作
基本使用方法
#文件的读取 f.read(size) #读取文件的内容,将文件的内容以字符串形式返回。 ''' size是可选的数值,指定字符串长度,如果没有指定size或者指定为负数,就会读取并返回整个文件。 当文件大小为当前机器内存两倍时就会产生问题,反之就尽可能大的size读取和返回数据,如果到了文件末尾,会返回空字符串。 ''' f.readline() #从文件中读取单独一行。 ''' 字符串结尾会自动加上一个换行符 ,只有当文件最后没有以换行符结尾时, 这一操作才会被忽略,这样返回值就不会有混淆。如果返回空字符串,表示到达率文件末尾,如果是空行,就会描述为 ,一个只有换行符的字符串。 ''' f.readlines() #一次读取所有,返回一个列表,列表的元素为文件行的内容。 '''可以通过列表索引的方式将文件的每一行的内容输出。 可以通过for循环迭代输出每一行的信息。 ''' f.flush() #把文件从内存buffer里强制刷新到硬盘 #文件的写入 f.write() #将要写入的内容以字符串的形式通过write方法写入文件中。 f.writelines() #括号里必须是由字符串元素组成的序列。 f.close() #关闭文件。对一个已经关闭的文件进行操作会报错。 #光标位置 f.tell() #返回光标在文件中的位置。 f.seek(offset,from) #在文件中移动文件指针,从from(0代表起始位置,1代表当前位置,2代表文件末尾)偏移offset个字节。 #查看文件信息 closed #查看文件是否已经关闭,返回布尔值。 mode #返回文件打开模式。 name #返回文件名。 #with 形式打开文件,里面的语句执行完后会自动关闭文件 with open('文件名','r') as f: f.read() #读大文件(大于10M以上) f = open("联系方式.txt",'r',encoding="utf-8") for line in f: print(line) f.close()
代码举例
# #只读模式 f=open(r'new.txt',encoding='utf-8') print('====>1',f.read()) print('====>2',f.read()) print(f.read()) print(f.readlines()) f.close() #写模式:文件不存在则创建,文件存在则覆盖原有的 f=open("new.txt",'w',encoding='utf-8') f.write('111 ') f.writelines(['2 ','3 ']) f.close() # 追加模式:文件不存在则创建,文件存在不会覆盖,写内容是追加的方式写 f=open('new.txt','a',encoding='utf-8') f.write('123 ') f.writelines(['aa ','bb ']) f.close() # 以二进制形式打开文件不需要编码 f = open(r"text.txt", "wb") f.write("路飞 ".encode()) # 写入utf-8二进制字节码 f.write("路飞 Yifei Qiao]".encode()) f.close() # 追加方式进行修改 f = open(r"兼职护士联系方式.txt",'ab') f.write(" 肛娘 北京 167 55 13523230322".encode("gbk")) f.close() #读写方式修改 f = open(r"兼职白领学生空姐模特护士联系方式.txt",'r+') f.seek(10) print(f.tell()) f.write("[路飞学城 luffycity]") f.close()
文件内光标移动
一: read(3):
1. 文件打开方式为文本模式时,代表读取3个字符
2. 文件打开方式为b模式时,代表读取3个字节
二: 其余的文件内光标移动都是以字节为单位如seek,tell,truncate
注意:
1. seek有三种移动方式0,1,2,其中1和2必须在b模式下进行,但无论哪种模式,都是以bytes为单位移动的
seek控制光标的移动,是以文件开头作为参照的。
tell当前光标的位置
2. truncate是截断文件,截断必须是写模式,但是不能用w或w+等方式打开,因为那样直接清空文件了,所以truncate要在r+或a或a+等模式下使用
def readable(self, *args, **kwargs): # real signature unknown 判断是否可读 def readline(self, *args, **kwargs): # real signature unknown 只读一行,遇到 or 为止 def seek(self, *args, **kwargs): # real signature unknown 把操作文件的光标移到指定位置 *注意seek的长度是按字节算的, 字符编码存每个字符所占的字节长度不一样。 如“路飞学城” 用gbk存是2个字节一个字,用utf-8就是3个字节,因此以gbk打开时,seek(4) 就把光标切换到了“飞”和“学”两个字中间。 但如果是utf8,seek(4)会导致,拿到了飞这个字的一部分字节,打印的话会报错,因为处理剩下的文本时发现用utf8处理不了了,因为编码对不上了。少了一个字节 def seekable(self, *args, **kwargs): # real signature unknown 判断文件是否可进行seek操作 def tell(self, *args, **kwargs): # real signature unknown 返回当前文件操作光标位置 def truncate(self, *args, **kwargs): # real signature unknown 按指定长度截断文件 *指定长度的话,就从文件开头开始截断指定长度,不指定长度的话,就从当前位置到文件尾部的内容全去掉。
文件操作案例
拷贝文件
#利用b模式,编写一个cp工具 # b模式 f=open('1.jpg','rb') data=f.read() # print(data) f=open('2.jpg','wb') f.write(data) print(data)
文件修改替换(硬盘上修改)
#_*_coding:utf-8_*_ import os f_name = "联系方式utf8.txt" f_new_name = "%s.new" % f_name old_str = "乔亦菲" new_str = "[乔亦菲 Yifei Qiao]" f = open(f_name,'r',encoding="utf-8") f_new = open(f_new_name,'w',encoding="utf-8") for line in f: #读取大文件 if old_str in line: new_line = line.replace(old_str,new_str) else: new_line = line f_new.write(new_line) f.close() f_new.close() os.rename(f_new_name,f_name) # 把新文件名字改成原文件的名字,就把之前的覆盖掉了
文件修改替换(内存中修改)
举例1:
f = open(r"斗罗大陆.txt", "r+") l = f.readlines() f.seek(0) # 指针指向文件开头 old_str = "唐三" new_str = "" for line in l[0::2]: # 只取部分字符 if old_str in line: line = line.replace(old_str,new_str) f.write(line+" ") f.truncate() # 对文件进行截取,如果文件之前为100M, # 修改后文件只覆盖了50M,如果不使用truncate不会整体覆盖,只会部分覆盖,后面剩余的50M内容会追加新文件中,修改后的文件大小不变 # 使用truncate后,文件就只有50M,他会把剩余的50M内容从当前write的指针后面进行截取 f.close()
举例2:
""" reform.txt 大胆点,伟大无比的力量自会来帮助你。——比锡耳王 大胆是取得进步所付出的代价。——雨果 不怕的人前面才有路。——有岛武信 世界是属于勇敢者的。——哥伦布 走自己的路,叫别人去说吧。——但丁 死是每个人都能做到的,拿出勇气活下去才是勇敢。——罗教·柯迪 人的一生中可能犯的错误,就是经常担心犯错误。——哈伯德 没有比害怕本身更害怕的了。——培根 你怕狼,就别到树林里去。——列宁 人生自古谁无死,留取丹心照汗青。——文天祥 未完待续…… """ """ 把文件reform.txt中的名人名言,改成“某某说:......”的形式, 把文件读入到内存中修改 """ f = open(r"reform.txt", "r+") l = f.readlines() f.seek(0) # 指针指向文件开头 for line in l[::2]: # 去掉空行" "字符 # ['大胆点,伟大无比的力量自会来帮助你。', '比锡耳王'] print(line) if "——" in line: old_str_li = line[:-1].split("——") # 去掉每行" "字符,按"——"进行分割 new_str = old_str_li[-1]+"说:"+old_str_li[0] f.write(new_str+" ") # 写入修改内容 else: f.write(line + " ") # 写入以前内容 f.truncate() # 对文件进行截取,进行整体覆盖 f.close()
Linux文件中字符替换
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # @Time : 2018/3/14 10:05 # @Author : hyang # @File : fileStrReplace.py # @Software: PyCharm import sys import os def print_arg(arg): """ 打印参数 :param arg: :return: """ for ind, val in enumerate(arg): if ind == 0: print(r"------执行%s输入参数为--------"% val) else: print(val, end=",") print() # 获得系统参数 v_arg = sys.argv if len(v_arg) != 4: print_arg(v_arg) print("---参数输入错误--") print("fileStrReplace.py 文件名 旧字符串 新字符串") else: f_name = v_arg[1].strip() old_str = v_arg[2].strip() # 旧字符 new_str = v_arg[3].strip() # 替换的新字符 f_new_name = "%s.new" % f_name replace_count = 0 # 字符替换次数 if not os.path.exists(f_name): print("%s文件不存在" % f_name) else: f_new = open(f_new_name, 'w') f = open(f_name, "r",) for line in f: # 读取大文件 if old_str in line: new_line = line.replace(old_str, new_str) # 字符替换 replace_count += 1 else: new_line = line f_new.write(new_line) # 内容写新文件 f.close() f_new.close() os.remove(f_name) # 删除原始文件 os.rename(f_new_name, f_name) # 把新文件名字改成原文件的名字,就把之前的覆盖掉了 if replace_count == 0: print("字符%s不存在" % (old_str)) else: print("文件替换成功,字符%s替换了%s次" % (old_str, replace_count))
执行结果