1 什么是文件?
文件是操作系统为用户或应用程序提供的一个读写硬盘的虚拟单位
文件的操作核心就:读、写 即我们只需要对于进行读写操作,就是对操作系统发起请求,然后由操作系统将用户或者应用程序 对文件的读写操作转换成具体的硬盘指令(比如控制盘片转动,控制机械手臂移动来读写数据)2 为什么要有文件?
因为内存无法永久保存数据,但凡我们想要永久保存数据都需要保存到硬盘中,
而操作文件就可以实现对硬件的操作
一、文件处理流程
1.打开文件,得到文件句柄并赋值给一个变量
2.通过句柄对文件进行操作
3.关闭文件
r模式,默认模式,文件不存在则报错
w模式,文件不存在则创建,文件存在则覆盖
a模式,文件不存在则创建,文件存在则不会覆盖,写内容会以追加的方式写(写日志文件的时候常用),追加模式是一种特殊的写模式
b(rb,wb,ab)模式:不用加encoding:utf-8
在python中
#1. 打开文件,得到文件句柄并赋值给一个变量f=open('a.txt','r',encoding='utf-8') #默认打开模式就为r#2. 通过句柄对文件进行操作data=f.read()#3. 关闭文件f.close()
注意:
读文件时,字符编码报错一定是存读文件的编码不一致,用什么编码存就用什么编码读.
f=open('a.txt','r')的过程分析
#1、由应用程序向操作系统发起系统调用open(...)#2、操作系统打开该文件,并返回一个文件句柄给应用程序#3、应用程序将文件句柄赋值给变量f
二、基本操作
1.文件打开模式
文件句柄=open('文件路径',‘模式’)
打开文件时,需要指定文件路径和以什么方式打开文件。
打开文件的模式有:
- r ,只读模式【默认模式,文件必须存在,不存在则抛出异常】
- w,只写模式【不可读;不存在则创建;存在则清空内容】
- x, 只写模式【不可读;不存在则创建,存在则报错】
- a, 追加模式【可读; 不存在则创建;存在则只追加内容】
#只读模式f=open(r'c.txt',encoding='utf-8')print('====>1',f.read())print('====>2',f.read())print(f.readable())print(f.readline(),end='')print(f.readline())print("="*20)print(f.read())print(f.readlines())f.close()#只写模式:文件不存在则创建,文件存在则覆盖原有的f=open("new.py",'w',encoding='utf-8')f.write('1111111111\n')f.writelines(['2222\n','2222548\n','978646\n'])f.close()
"+" 表示可以同时读写某个文件
- r+, 读写【可读,可写】 文件不存在,报错 存在,指针开头
- w+,写读【可读,可写】 文件不存在,创建空文件 存在,清空文件
- x+ ,写读【可读,可写】
- a+, 写读【可读,可写】 文件不存在,创建空文件 存在指针末位
"b"表示以字节的方式操作
- rb 或 r+b
- wb 或 w+b
- xb 或 w+b
- ab 或 a+b
注:以b方式打开时,读取到的内容是字节类型,写入时也需要提供字节类型,不能指定编码
练习,利用b模式,编写一个cp工具,要求如下:
1. 既可以拷贝文本又可以拷贝视频,图片等文件
# b模式f=open('1.jpg','rb')data=f.read()# print(data)f=open('2.jpg','wb')f.write(data)print(data)
操作文件的方法
#掌握f.read() #读取所有内容,光标移动到文件末尾f.readline() #读取一行内容,光标移动到第二行首部f.readlines() #读取每一行内容,存放于列表中f.write('1111\n222\n') #针对文本模式的写,需要自己写换行符f.write('1111\n222\n'.encode('utf-8')) #针对b模式的写,需要自己写换行符f.writelines(['333\n','444\n']) #文件模式f.writelines([bytes('333\n',encoding='utf-8'),'444\n'.encode('utf-8')]) #b模式#了解f.readable() #文件是否可读f.writable() #文件是否可读f.closed #文件是否关闭f.encoding #如果文件打开模式为b,则没有该属性f.flush() #立刻将文件内容从内存刷到硬盘f.name
上下文管理
with open('e.txt', 'rb') as f, open('j.txt', 'wt', encoding='utf-8') as f1: # 文件的操作 src_data = f.read() res = src_data.decode('utf-8') print(res,type(res)) f1.write(res)with open('e.txt', 'rb') as f, \ open('j.txt', 'wb') as f1: # 文件的操作 f1.write(f.read())
文件拷贝
src_file=input('源文件:')copy_file=input('目标文件:')with open(src_file,'r') as f,open(copy_file,'w') as f2: for line in f: f2.write(line)
文件内光标移动
一: read(3):
1. 文件打开方式为文本模式时,代表读取3个字符
2. 文件打开方式为b模式时,代表读取3个字节
二: 其余的文件内光标移动都是以字节为单位如seek,tell,truncate
注意:
1. seek 有三种移动方式0,1,2,其中1和2必须在b模式下进行,但无论哪种模式,都是以bytes为单位移动的
# f.seek(offset,whence)#offset代表文件的指针的偏移量,单位是字节bytes#whence代表参考物,有三个取值#0:参照文件的开沟#1:参照当前文件指针所在位置#2: 参照文件末尾#ps:快速移动到文件末尾f.seek(0,2)#强调:其中whence=1和whence=2只能在b模式下使用
2. truncate是截断文件,所以文件的打开方式必须可写,但是不能用w或w+等方式打开,因为那样直接清空文件了,所以truncate要在r+或a或a+等模式下测试效果
# ab a+b r+bf=open('b.txt',mode='at',)f.truncate(9) # 参照物永远是文件开头f.close()
3. f.tell() 每次统计都是从文件开头到当前指针所在位置
文件修改
文件的数据是存放于硬盘上的,因而只存在覆盖、不存在修改这么一说,我们平时看到的修改文件,都是模拟出来的效果,具体的说有两种实现方式:
方式一:将硬盘存放的该文件的内容全部加载到内存,在内存中是可以修改的,修改完毕后,再由内存覆盖到硬盘(word,vim,nodpad++等编辑器)
#修改文件内容的方式一:#思路:先将原文件内容一次性全部读入内存,然后在内存修改完毕后,再#覆盖写回原文件#优点:在修改期间,文件内容只有一份#缺点:当文件过大的情况下或占用过多的内存空间# with open('d.txt','rt',encoding='utf-8') as read_f:# msg=read_f.read()# msg=msg.replace('alex','xiang')# # print(msg)## with open('d.txt','wt',encoding='utf-8') as write_f:# write_f.write(msg)
方式二:将硬盘存放的该文件的内容一行一行地读入内存,修改完毕就写入新文件,最后用新文件覆盖源文件
#修改文件内容的方式二:#思路:#1、以读的方式打开原文件,以写的方式打开一个新文件#2、从原文件中循环读取每一行内容修改后写入新文件#3、删除原文件,将新文件重命名为原文件的名字#优点:同一时刻只有一行内容存在于内存中#缺点:在修改期间,文件内容始终存在两份,但修改完毕后会只留一份import oswith open('d.txt','rt',encoding='utf-8') as read_f,\ open('d.txt.swap','wt',encoding='utf-8') as write_f: for line in read_f: write_f.write(line.replace('xiang','ALEXSB'))os.remove('d.txt') # 删除老文件os.rename('d.txt.swap','d.txt')