文件处理
文件相关概念
文件:文件是操作系统给予用户操作硬盘而诞生的逻辑概念
客户操作硬盘是通过发起系统调用,然后由操作系统进一步对硬盘读写操作
python操作文件一般调用的是open()方法
1. open()方法操作文件内容的模式有:
t(不指定默认) ------>用于str类型的数据
b(bytes类型二进制)----->用于非str类型的数据
2. open()方法操作文件内容的方法有:r、w、a、+
t模式
open()操作文件的流程
#!/usr/bin/python or /usr/bin/env python ##用于脚本执行时指定python解释器
# coding:utf-8 ##用于指定读取代码使用的编码格式
f=open(r'D:\20210529\nab'.mode='rt',encoding='utf-8')
f.close() #关闭操作系统申请的内存空间
del f #关闭解释器申请的内存空间
文件路径:可以写绝对路径,也可以写相对路径,window中的\n会发生转义,故路径前加r(rawstring)
模式:不指定,默认的模式是rt,t模式一定要指定编码格式,否则报错;b模式一定不能指定编码格式
encoding:不加encoding,默认使用的是系统默认的编码格式,windows(GBK),linux(utf-8)**
- open()方法和其他方法类似,都会占用解释器的内存空间,不过占用的空间比较小
- open()方法通过解释器发动系统调用,并在系统开辟了内存空间,
- 对硬盘发起读写操作
- 读操作会将磁盘中的二进制bytes类型的数据根据指定的encoding编码格式解码成unicode,加载到内存
然后应用程序通过索引将unicode对应的字符打印出来。print()—默认会将unicode转换未字符类型
- 读操作会将磁盘中的二进制bytes类型的数据根据指定的encoding编码格式解码成unicode,加载到内存
为方便我们对内存变量的回收,我们引入了with语法
with open(r'/tmp/test/code1',encoding='utf-8') as f:
res=f.read()
print(res)
操作内容介绍
- r:只读(特点:文件不存在则报错,文件存在则将指针移到文本开头开始读;写报错)
with open(r'a.txt',mode='rt',encoding='utf-8') as f:
for line in f:
print(line.strip(),end='')
#strip默认会去掉空格和\n,end默认不指定也是以\n分割;
with上下文没有关闭,循环读,每次读指针会从当前位置往后读,直到结束。
应用场景:
-w: 只写(特点:文件不存在则创建,文件存在则删除文本内容指针移到文本开头,读报错)
with open(r'a.txt',mode='wt',encoding='utf-8') as f:
for i in range(3):
f.write('nihao\n')
#\n是为了写入时换行,循环写入时每次指针会从当前位置让后写,直到循环结束
应用场景:
-a:追加写(特点:文件不存在则创建,存在则指针移到文本末添加字符串,读报错)
with open(r'b.txt',mode='at',encoding='utf-8') as f:
f.write('test')
...
pass
- +: 附加本身不具备的功能,以本身功能为主
(注:r+t:可读可写,但是文件不存在则报错,每次读指针都会移到文本头。w+t:类似)
with open(r'a.txt',mode='r+t',encoding='utf-8') as f:
...
案例1:用户名密码的校验
input_name=input("请输入您的名字:".strip())
input_passwd=input("请输入您的密码:".strip())
with open(r'a.txt',mode='rt',encoding='utf-8') as f:
for line in f :
username,password=line.strip().split(':')
if username==input_name and password==input_passwd:
print("login successful")
break
else:
print('用户名密码不正确')
案例2:数据拷贝
src_file=input("请输入你的源文件路径:".strip())
dest_file=input("请输入你的目标文件路径:".strip())
with open(src_file,mode='rt',encoding='utf-8' ) as f,\
open(dest_file,mode='wt',encoding='utf-8') as f1:
res=f.read()
f1.write(res)
- x:只写(文存在则报错,文件不存在则创建)
二进制、字符、字节之间的转换
name1="xiaoming"
name2="小明"
name3=name1.encode("utf-8")
name4=b"xiaoming" #字符串前加b可以将字符串转为bytes类型,前提是字符必须为英文字符
name5=bytes(name1.encode("utf-8")) #将字符串类型的数据转换为bytes类型
字节类型会根据编码类型编码成对应的二进制存入到硬盘中
b模式
with open(r'a.txt',mode="rb") as f:
res=f.read()
print(res)
#b模式是直接将硬盘中的二进制读入到内存中,打印出来就是bytes类型
**注意:**换行符根据系统可能不同,类linux系统是\n ;window系统是\r\n ;
b模式和t模式的区别
- b模式读写都是以字节为单位,t模式除了read()以字符为单位,其他也是以字节为单位
- b模式一定不能指定encoding,t模式一定要指定encoding
- b模式可以作用于认以类型的文件,t模式只能作用于文本文件
- 在操作文本文件上,t模式做了简化(不需要指定编码格式),b模式是一步一步进行的(需要指定编码)
例:文件拷贝
方案一:
src_file=input("请输入您的源文件:".strip())
dest_file=input("请输入您的目标文件:".strip())
with open(src_file,mode='rb') as f,\
open(dest_file,mode="wb") as f1:
res=f.read()
f1.write(res)
#很明显,如果文件过大,read回将文件一次性读入到内存中,会损耗机器的性能,需要改善
方案二:
src_file=input("请输入您的源文件:".strip())
dest_file=input("请输入您的目标文件:".strip())
with open(src_file,mode='rb') as f,\
open(dest_file,mode="wb") as f1:
for line in f:
res=bytes(line)
f1.write(res) #只有t模式read读取单位为str,其他模式的其他操作都是bytes类型
#这个也会存在问题,一行的内容较多,也会占用内存
方案三:
src_file=input("请输入您的源文件:".strip())
dest_file=input("请输入您的目标文件:".strip())
with open(src_file,mode='rb') as f,\
open(dest_file,mode="wb") as f1:
while True:
res=f.readline(200)
if len(res)==0:
break
else:
f1.write(res)
open打开文件赋值给变量后,变量的文件类型
with open(r'a.txt',mode='wt',encoding="utf-8") as f :
print(f,type(f),id(f))
result:
<_io.TextIOWrapper name='a.txt' mode='wt' encoding='utf-8'> <class '_io.TextIOWrapper'> 2268427498160
with open(r'a.txt',mode='wb') as f :
print(f,type(f),id(f))
result:
<_io.BufferedWriter name='a.txt'> <class '_io.BufferedWriter'> 2781964051200