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 ') f.writelines(['2222 ','2222548 ','978646 ']) 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 222 ') #针对文本模式的写,需要自己写换行符 f.write('1111 222 '.encode('utf-8')) #针对b模式的写,需要自己写换行符 f.writelines(['333 ','444 ']) #文件模式 f.writelines([bytes('333 ',encoding='utf-8'),'444 '.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+b f=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 os with 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')