目录
一、什么是文件
1.什么是文件、为什么要用文件
文件:操作系统提供给应用程序来操作硬盘的虚拟概念
文件的作用:有了文件的概念,我们无需再去考虑操作硬盘的细节,只需要关注操作文件的流程
# 应用程序运行过程中的数据都是先存放于内存中,若想永久保存下来,就必须保存于硬盘中。应用程序若想操作硬盘必须通过操作系统。
# 而文件就是操作系统提供给应用程序来操作硬盘的虚拟概念,用户或应用程序对文件的操作,就是向操作系统发起调用,然后由操作系统完成对硬盘的具体操作。
二、文件操作的流程
1.文件操作的流程
操作文件的流程简单来说就是:
打开文件>>>> 调用文件>>>> 关闭文件
1.打开文件 open方法
由应用程序向操作系统发起系统调用 open(...),操作系统打开该文件,对应一块硬盘空间,并且返回一个文件对象赋值给一个变量 f
# 如:
f = open('a.txt','r',encoding='utf8')
f = open(文件路径, 读写模式, encoding='utf8')
2.调用文件
调用文件对象下的读/写方法,会被操作系统转换为读/写硬盘的操作
data = f.read()
f.write()
3.关闭文件
向操作系统发起关闭文件的请求,回收系统资源
f.close()
open方法的第一个参数是文件路径,并且撬棍和一些字母的组合回产生特殊含义导致路径查找混乱,为了解决该问题可以在字符串的路径前面加字母r
D:\a\n\t
r'D:\a\n\t'
以后涉及到路径的编写,推荐加上r
2.资源回收与 with方法
- 资源回收
打开一个文件包含两部分资源:
1) 应用程序的变量f
2) 操作系统打开的文件
在操作完毕一个文件时,必须把与该文件的这两部分资源全部回收,回收方法为:
1.f.close() 方法 # 回收操作系统打开的文件资源
2.del f # 回收应用程序级的变量
'''
del f一定要发生在f.close()之后,否则就会导致操作系统打开的文件无法关闭,白占用了资源
而python的垃圾回收机制 帮助我们无需考虑 del f,只需要在操作完毕文件后,使用f.close()操作即可,而python还提供了with方法来帮助避免忘记f.close()操作
'''
- with上下文管理
1. with上下文管理好处在于子代码运行结束自动调用close方法关闭资源
with open('a.txt', 'r', encoding='utf8') as f:
with子代码块
2.with支持打开多个文件,用逗号隔开
# 如:
with open('a.txt', 'r') as read_f, open('b.txt', 'w') as write_f:
data = read_f.read()
write_f.write(date)
- 指定操作文本文件的字符编码
f = open(...)由系统打开文件,如果文件为文本文件,会涉及到字符编码问题。
如果没有给 open 指定编码,那么文本文件的默认编码是由操作系统决定的,windows默认是gbk模式,linux默认是utf8
可以指定以什么方式打开,在后面加上encoding='...'
f = open('a.txt', 'r', encoding='utf8') # 以utf8编码打开
三、文件的操作模式
1.文件的读写模式
r(默认模式):只读模式
w:只写
a:只追加写
- 1.1 r模式
r只读模式:只能读不能写
文件路径不存在时,会直接报错;
文件存在指针直接跳到文件开头的开头
with open('a.txt', mode='r', encoding='utf-8') as f:
res = f.read() # 会想文件的内容从硬盘读取到内存,再赋值给变量名 res
- 1.2 w模式
w只写模式:只能写不能看
文件路径不存在,自动创建空文档;
文件存在会清空文件内容,再写入
with open(r'a.txt', 'w', encoding='utf8') as f:
f.write('今天是周一\n')
f.write('明天是周一\n')
f.write('后天是周一\n')
强调:
1 文件连续写入的情况下,后面写入的内容紧跟在前面写的内容之后,换行符需要自己添加,并且在后续数据读取比对的时候也一定要注意换行符的的存在
2.如果重新以w模式打开文件,会清空文件内容
- 1.3 a模式
a只追加模式:文件末尾添加数据
文件路径不存在:自动创建
文件路径存在:自动将文件指针移动到文件末尾等待追加内容
with open(r'a.txt', 'a', encoding='utf8') as f:
f.write('放假七天乐')
with open(r'a.txt', 'a', encoding='utf8') as f:
pass
# 当我们在编写代码的时候 有些部分不知道写什么具体代码 但是也不能空着不写
# 这个时候可以使用关键字
# 1 pass
# 2 ...
# 只补全语法不执行功能 本身没有任何的含义
- 1.4 +模式:可读可写
r+ w+ a+ :可读可写模式,一般不使用
2.文件的操作模式
大前提:tb模式均不能单独使用,必须与r/w/a 之一结合使用
t(默认的模式):文本模式
1.只能操作文本文件
2.读写文件以字符串为单位
3.必须制定encoding参数,如果不知道则会采用计算机的默认编码
b 二进制模式( bytes模式):
1.可以操作任意类型的文件
2.读写文件以 bytes字节为单位
3.一定不能指定encoding参数,因为它已经是二进制模式了 不需要编码
- 2.1 t模式
# t 模式:如果我们指定的文件打开模式为r/w/a,其实默认就是 rt/wt/at
with open('a.txt', 'rt', encoding='utf8') as f:
res = f.read()
print(type(res)) # <class 'str'> 输出结果为字符串
with open('a.txt', 'wt', encoding='utf8') as f:
res = '明天星期一'
f.write(res) # 写入的结果也是字符串类型
#强调: t模式 只用于文本类型的文件,读写都以字符串为单位,而存取硬盘的本质都是二进制形式,当使用t模式时,内部帮我们做了编码与解码
- 2.2 b模式
# b 模式:读写都是以二进制位单位
with open('今日内容.md', 'rb') as f:
res = f.read()
print(type(res)) # <class 'bytes'> 输出结果为字节
with open('a.txt', 'wt') as f:
res = '明天星期一'
ress = res.encode('utf8')
f.write(res) # b模式下写入的结果也是bytes类型
强调:b模式与t模式的对比
1.在操作纯文本类型的文件时,t模式省去了编码与解码的环节,b模式则需要编码与解码
2.针对非文本类型的文件(视频、图片、音频等)只能使用b模式
3.二进制模式与文本模式针对文件路径是否存在的情况下 规律是一样的!!!
四、操作文件的方法
1.需掌握的方法
- 读操作
# 读操作
1.f.read() # 一次性读取文件,执行完该操作后,光标停留在文件末尾,继续读取则没有内容,括号内还可以填写数字,在文本模式 t模式下,表示读取几个字符
2.f.readline() # 读取一行内容,光标移动到第二行首部
3.f.readlines() # 读取每一行内容,会按照行数组织成列表中的一个个数据值
# 强调:避免内存溢出
# f.read()与f.readlines()都是一次性读取内容, 如果内容过大会造成内存溢出,若还想将内容全部读入内存,必须分多次读入,有两种方式
# 方式一:for循环
with open('a.txt', 'rt', encoding='utf8') as f:
for line in f:
print(line) # 同一时刻只读入一行内容到内存中
# 方式二: b模式
with open('1.avi', 'rb') as f:
while True:
data = f.read(1024) # 同一时刻只读入1024个bytes到内存中
if len(data) == 0
break
print(data)
- 写操作
# 写操作
1.f.write('aaaa\n') # 针对文本模式的写,需要自己写换行符
2.f.write('aaaa\n', encoding='utf8') # 针对b模式的写,需要自己写换行符
3.f.writelines(['111\n','333\n']) # 文件模式,接收一个列表,一次性将列表中所有的的数据值写入
4.f.writelines([bytes('111\n',encoding='utf8'),'111\n'.encode('utf8')]) # b模式
2.了解的方法
f.readable() # 判断文件是否可读
f.writable() # 判断文件是否可写
f.closed # 文件是否关闭
f.encoding # 如果文件打开模式为b,则没有该属性
f.flush() # 立刻将文件内容从内存刷到硬盘 等价于 crtl + s
五、文件内光标的移动
# 文件内指针的移动都是以bytes为单位的,唯一例外的是t模式下的read(n),n以字符为单位
with open('a.txt', 'rt', encoding='utf8') as f:
data = f.read(3) # 读取3个字符
with open('a.txt', 'rb') as f:
data = f.read(3) # 读取3个bytes
1. f.seek()方法:主动控制光标的移动
f.seek(光标移动的字节数offset, 模式whence)
0:默认模式 ,指针移动的字节以文件开头
文本和二进制模式都可以使用
1:基于当前位置
只有二进制模式可以使用
2:基于文件末尾
只有二进制模式可以使用
# print(f.read(3).decode('utf8'))
六、文件的修改
1.计算机硬盘修改数据的原理
硬盘删除数据的原理:
硬盘删除数据不是修改,而是用新内容覆盖就内容,而硬盘中的数据是无法被修改的智能覆盖
# 文件a.txt内容如下
张艺谋 山东 123
# 执行操作
with open('a.txt',mode='r+t',encoding='utf-8') as f:
f.seek(9)
f.write('<妇女主任>')
# 文件修改后的内容如下
张艺谋<妇女主任> 123
2.文件内容修改
# 方式一:覆盖写,将文件一次性全部读入内存,然后在内存中修改然后在覆盖会原文件
# 优点:在文件修改过程中同一份数据只有一份
# 缺点:内存占用过多
with open(r'a.txt','r',encoding='utf8') as f:
data = f.read() # 先读取文件a.txt
with open(r'a.txt', 'w', encoding='utf8') as f1:
f1.write(data.replace('jason', 'tony')) # 在内存中修改a.txt文件
# 方式二:换地方写:以读的方式代开原文件,以写的方式打开一个临时文件,一行行读取源文件内容,修改完后写入临时文件,然后删掉源文件,将临时文件重命名为源文件
# 优点:占用内存少
# 缺点:在文件修改过程中同一份数据存了两份
import os
with open('a.txt','r',encoding='utf8') as read_f, \
open('.a.txt.swap','w',encoding='utf8') as write_f:
for line in read_f:
write_f.write(line.replace('tony','kevin'))
os.remove('a.txt') # 删除a.txt
os.rename('.a.txt.swap', 'a.txt') # 重命名文件
练习题
1.编写简易版本的拷贝工具
自己输入想要拷贝的数据路径 自己输入拷贝到哪个地方的目标路径
任何类型数据皆可拷贝
ps:个别电脑C盘文件由于权限问题可能无法拷贝 换其他盘尝试即可
#1.获取想要拷贝的文件路径
source_file_path = input('请输入您想要拷贝的文件路径>>>:').strip()
#2.获取目标文件的路径
target_file_path = input('请输入您想要拷贝到哪个地方的路径>>>:').strip()
#3.打开第一个文件路径 读取内容写入第二个文件路径中
with open(r'%s' % source_file_path, 'rb') as read_f, open(r'%s' % target_file_path, 'wb') as write_f:
for line in read_f:
write_f.write(line)
2.利用文件充当数据库编写用户登录、注册功能
文件名称:userinfo.txt
基础要求:
用户注册功能>>>:文件内添加用户数据(用户名、密码等)
用户登录功能>>>:读取文件内用户数据做校验
ps:上述功能只需要实现一次就算过关(单用户) 文件内始终就一个用户信息
拔高要求:
用户可以连续注册
用户可以多账号切换登录(多用户) 文件内有多个用户信息
ps:思考多用户数据情况下如何组织文件内数据结构较为简单
提示:本质其实就是昨天作业的第二道题 只不过数据库由数据类型变成文件
while True:
print("""
1.注册功能
2.登录功能
""")
choice = input('请选择您想要执行的功能编号>>>:').strip()
if choice == '1':
username = input('please input your username>>>:').strip()
password = input('please input your password>>>:').strip()
# 2.校验用户名是否已存在
with open(r'userinfo.txt', 'r', encoding='utf8') as f:
for line in f: # 'jason|123'
real_name, real_pwd = line.split('|')
if username == real_name:
print('用户名已存在 无法完成注册')
break # 一旦重复 没有必要继续往下校验是否重复了 直接结束循环
else:
with open(r'userinfo.txt', 'a', encoding='utf8') as f1:
f1.write(f'{username}|{password}\n')
print(f'用户{username}注册成功')
elif choice == '2':
# 1.获取用户名和密码
username = input('please input your username>>>:').strip() # 'jason'
password = input('please input your password>>>:').strip() # '123'
# 2.打开文件读取内容并校验
with open(r'userinfo.txt', 'r', encoding='utf8') as f:
for line in f: # 'jason|123\n'
real_name, real_pwd = line.split('|') # 'jason' '123\n'
if real_name == username and real_pwd.strip('\n') == password:
print('登录成功')
break
else:
print('用户名或密码错误')
else:
print('没有该功能编号')
标签:文件,encoding,python,utf8,模式,处理,txt,open
From: https://www.cnblogs.com/DuoDuosg/p/16773312.html