文件(读写、方法、光标、内容修改)
文件的基本操作
文件的概念
应用程序运行过程中产生的数据最先都存放在内存中,要是想永久保存下来,必须保存于硬盘中,应用程序要是想操作硬件必须通过操作系统,而文件就是操作系统提供给应用程序来操作硬盘的虚拟概念,用户或应用程序对文件的操作,就是操作系统发起调用,然后操作系统完成对硬盘的具体操作(就是操作系统暴露给用户操作硬盘的快捷方式)。
eg:双击一个文件 其实就是硬盘中将数据加载到内存
ctrl+s 保存文件,其实是将内存中的数据刷到硬盘保存
代码打开的文件的两种方式
方式1:
1.打开文件,由应用程序向操作系统发起系统调用open(..),操作系统打开该文件,对应一块硬盘空间,并返回一个文件对象赋值给一个变量f
f = open('a.txt','r',encoding='utf-8')
# f = open(文件路径,读写模式,encoding='utf8')
2.调用文件对象的读/写,会被操作系统转换为读/写硬盘的操作
date = f.read()
3.向操作系统发起关闭文件的请求,回收系统资源
f.close()
方式2:with 上下文管理
1.在执行完子代码块后,with会自动执行f.close()关闭资源
with open('a.txt','r',encoding='utf8') as f1:
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(data)
"""
open方法的第一参数是文件路径 并且撬棍跟一些字母的组合胡产生特殊的含义导致路径查找混乱 为了解决该问题可以在字符串的路径前面加字母r
D:\a\n\t
r'D:\a\n\t
以后涉及到路径的编写 推荐加上r
"""
资源回收方法
1.f.close() # 回收操作系统打开的文件资源
2.del f # 回收应用程序级的变量
指定操作文本文件的字符编码
f = open(...)是由操作系统打开文件,如果打开的是文本文件,会涉及到字符编码问题,如果没有为open指定编码,那么打开文本文件的默认编码很明显是操作系统说了算,操作系统会用自己的默认编码去打开文件,在windows下是gbk,在linux下是utf-8。
这就用到了上节课讲的字符编码的知识:若要保证不乱码,文件以什么方式存的,就要以什么方式打开。
f = open('a.txt','r',encoding='utf-8')
文件读写模式
1.'r' 只读模式:只能读不能写
1.文件路径不存在:会直接报错
with open(r'b.txt','r',encoding='utf8') as f3:
print(f3.read()) # FileNotFoundError: [Errno 2] No such file or directory: 'b.txt'
2.文件路径存在:正常读取文件内容,文件内指针直接跳到文件开头
with open(r'a.txt','r',encoding='utf8') as f4:
print(f4.read())
2.'w' 只写模式:只能写不能看
1.文件路径不存在:自动创建
with open(r'c.txt','w',encoding='utf8') as f4:
pass
2.文件路径存在:先清空文件内容 之后再写入,文件指针跑到文件开头
with open(r'a.txt','w',encoding='utf8') as f5:
f5.write('假期综合征 及时调整\n')
f5.write('每天都是新的内容\n')
f5.write('学习使人快乐\n')
f5.write('开开心心\n')
f5.write('我又新增一行且不换行')
f5.write('嘿嘿哈哈哈呵呵\n')
图如下
"""
强调:换行符需要自己添加,并且在后续数据读取对比的手也一定要注意它的存在
注意:
1.在文件不关闭的情况下,连续的写入,后写的内容一定跟在前面写内容的后面》》》》》》待考察
2.如果重新以w模式打开文件,则会清空文件内容
"""
3.'a' 只追加模式:文件末尾添加数据
1.文件路径不存在:自动创建空文档,文件指针直接移动到文件末尾
with open(r'b.txt','a',encoding='utf8') as f6:
pass
2.文件路径存在:自动在末尾等待追加内容
with open(r'a.txt','a',encoding='utf8') as f7:
f7.write('又可以开心的学习')
4.+ 模式的使用(了解)
1.r+ w+ a+ :可读可写
2.平时工作中,我们只单纯使用r/w/a,要么只读,要么只写,一般不用可读可写的模式
"""
当我们在编写代码的时候 有些部分不知道写什么具体代码 但是也不能空着不写
这个时候可以使用关键字
pass
...
只补全语法不执行功能 本身没有任何的含义
"""
关于\n的作用如上
文件操作模式
t 文本模式
默认的模式 我们上面所写的r w a 其实全称是 rt wt at
1.只能操作文本文件
2.读写都是以字符为单位
3.需要指定encoding参数,如果不知道则会采用计算机默认的编码
b 二进制模式(bytes模式)
不是默认的模式 需要自己指定 rb wb ab
1.可以操作任意类型的文件
2.读写都是以bytes为单位
3.不需要指定encoding参数,因为它已经是二进制模式了 不需要编码
二进制模式与文本模式针对文件路径是否存在的情况下 规律是一样的!!
t模式的使用
with open(r'a.txt','rt',encoding='utf8') as f:
res = f.read()
print(res,type(res)) # 学习使人快乐 <class 'str'>
with open(r'a.txt','wt',encoding='utf8') as f1:
f1.write('文本模式下的可写功能')
# a.txt里面的文件-----文本模式下的可写功能
with open(r'a.txt','at',encoding='utf8') as f2:
f2.write('文本模式下的追加模式的使用')
# a.txt里面的文件内容-----文本模式下的可写功能文本模式下的追加模式的使用
b模式的使用
"""b模式的使用 """
with open(r'a.txt','rb') as f:
date = f.read()
print(type(date)) # <class 'bytes'>
with open(r'a.txt','wb') as f1:
# f1.write('hahha') a bytes-like object is required, not 'str'
b = '你好' # 字符串类型
res = b.encode('utf8') # 转为bytes类型
f1.write(res) # 在b模式下写入文件的只能是bytes类型
t模式和b模式的区别
1.在操作纯文本文件方法t模式帮我们省去了编码与解码的环节,b模式则需要手动编码与解码,此时t模式更方便
2.针对非文本文件(如图画、视频、音频等)只能使用b模式
文件诸多方法
1.read()
一次性读取文件内容,并且光标停留在文件末尾,继续读取则没有内容(光标已经在末尾了)
并且当文件内容比较多的时候,该方法还可能会造成计算机内存溢出
括号还可以填写数字,在文本模式下,表示读取几个字符
2.for循环
一行行读取文件内容 避免内存溢出现在的产生
3.readline()
一次只读一行
4.readlines()
一次性读取文件内容,会按照行数组织成列表的一个个数据值
5.readable()
判断文件是否具备读数据的能力
6.write()
写入数据
7.writeable()
判断文件是否具备写数据的能力
8.writelines()
接收一个列表 一次性将列表中所有的数据值写入
9.flush()
将内存中文件数据立刻刷到硬盘 等价于ctrl +s
如何解决f.read()文件过大溢出的情况?
首先要for循环遍历,一行一行读取内容 ,如图下
文件内光标的移动
with open(r'a.txt', 'rb') as f:
print(f.read())
f.seek(3,0) # 3是位移量,0是模式
print(f.read())
f.seek(0, 0)
print(f.read())
# print(f.read(2).decode('utf8'))
# f.seek(-1, 2)
# print(f.tell()) # 返回光标距离文件开头产生的字节数
"""
seek(offset, whence)
offset是位移量 以字节为单位
whence是模式 0 1 2
0是基于文件开头
文本和二进制模式都可以使用
1是基于当前位置
只有二进制模式可以使用
2是基于文件末尾
只有二进制模式可以使用
"""
# print(f.read(3).decode('utf8'))
光标的移动实操
with open(r'a.txt','r',encoding='utf8') as f:
print(f.read(3)) # 文本模式下 3 是字节
print(f.read(3))
print(f.read(3))
print('----------------')
with open(r'a.txt','rb') as f1:
# print(f1.read(5)) # b'\xe8\xb5\xb0\xe7\x9d'
# print(f1.read(5).decode('utf8')) # 二进制模式下 3 是字节的意思
print(f1.read(18).decode('utf8'))
结果如图
光标的移动![光标的移动]
文件内光标移动(了解)
import time
with open(r'a.txt','rb') as f: # a.txt 文件里面的内容必须要通过代码添加,不能手动添加
f.seek(0,2) # 2 打开文件光标处于是文件末尾
while True:
line = f.readline() # 光标在文件末尾,不执行
if len(line) == 0:
# 没有内容
time.sleep(0.5)
else:
print(line.decode('utf8'), end='')
图如下
计算机硬盘修改数据的原理(了解)
硬盘写数据可以看出是在硬盘刻字,一旦需要修改中间内容,则需要重新刻字,应为刻过的字不可能从中间再分开
硬盘删除数据的原理(固态是数据计算)
不是直接删除二十改变状态 等待后续数据的覆盖才会被真正的删除
文件内容修改(了解)
修改文件的方法有两种:
方式1:覆盖写
实现思路:将文件内容发一次性全部读入内存,然后在内存中修改完毕后再覆盖写回原文件
优点: 在文件修改过程中同一份数据只有一份
缺点: 会过多地占用内存
with open(r'a.txt','r',encoding='utf8') as f:
data = f.read()
with open(r'a.txt','w',encoding='utf8') as f1:
f1.write(data.replace('jason','tony'))
方式2:换地写
"""先在另外一个地方写入内容,然后将源文件删除,将新文件按命名成源文件"""
实现思路:以读的方式打开原文件,以写的方式打开一个临时文件,一行行读取原文件内容,修改完后写入临时文件...,删掉原文件,将临时文件重命名原文件名
优点: 不会占用过多的内存
缺点: 在文件修改过程中同一份数据存了两份
import os
with open(r'a.txt','r',encoding='utf8') as f,open(r'aaa.txt','w',encoding='utf8') as f2:
for line in f:
f2.write(line.replace('toy','kevin'))
os.remove('a.txt') # 删除a.txt
os.rename('aaa.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_f1,open(r'%s'%target_file_path,'wb',)as write_f2:
for line in read_f1:
write_f2.write(line)
2.利用文件充当数据库编写用户登录、注册功能
文件名称:userinfo.txt
基础要求:
用户注册功能>>>:文件内添加用户数据(用户名、密码等)
用户登录功能>>>:读取文件内用户数据做校验
ps:上述功能只需要实现一次就算过关(单用户) 文件内始终就一个用户信息
拔高要求:
用户可以连续注册
用户可以多账号切换登录(多用户) 文件内有多个用户信息
ps:思考多用户数据情况下如何组织文件内数据结构较为简单
提示:本质其实就是昨天作业的第二道题 只不过数据库由数据类型变成文件
""" 基础注册"""
# 用户注册功能>>>:文件内添加用户数据(用户名、密码等)
# 1.获取用户的用户名和密码
username = input('请输入用户名的名字>>>:').strip()
password = input('请输入用户名的密码>>>:').strip()
# 2.构建用户名和密码
user_data = f'{username}|{password}' # jason|123
# 2.打开文件写入数据
with open(r'userinfo.txt','w',encoding='utf8') as f:
f.write(user_data)
""" 基础登录"""
# 用户登录功能>>>:读取文件内用户数据做校验
# 1.获取用户用户名和密码
username = input('请输入用户名>>>>:').strip()
password = input('请输入用户名的密码>>>:').strip()
# 2.读取文件内容
with open(r'userinfo.txt','r',encoding='utf8') as f2:
real_name,real_pwd = f2.read().split('|')
print(real_name,real_pwd)
# 3.校验用户名和密码
if username == real_name and password == real_pwd:
print('登录成功')
else:
print('用户名或者密码错误')
""" 进阶版注册功能"""
# 1.获取用户名和密码
username = input('please input your name>>>>:').strip()
password = input('please input your password>>>>:').strip()
# 2.判断用户名是否存在
with open(r'userinfo.txt','r',encoding='utf8') as f1:
for line in f1: # kiki|123
real_name, real_pwd = line.split('|')
if real_name==username:
print('用户名已经存在,无法注册')
break # 一旦重复 没有必要继续往下校验是否重复了 直接结束循环
else:
with open(r'userinfo.txt','a',encoding='utf8') as f2:
f2.write(f'{username}|{password}\n')
print(f'{username}注册成功')
""" 进阶版登录功能"""
# 1获取用户名和密码
username = input('please input your name>>>:').strip()
password = input('please input your pwd>>>>:').strip()
# 2.读取内容并校验
with open(r'userinfo.txt','r',encoding='utf8') as f2:
for line in f2: # kiki|123\n
real_name, real_pwd = line.split('|') # kiki 123\n
if username == real_name and password == real_pwd.strip('\n'):
print('登录成功')
break
else:
print('用户名或密码错误')
while True:
print("""
1.注册功能
2.登录功能
""")
choice = input('please choice number>>>: ').strip()
if choice == '1':
# 1.获取用户名和密码
username = input('please input your name>>>>:').strip()
password = input('please input your password>>>>:').strip()
# 2.判断用户名是否存在
with open(r'userinfo.txt', 'r', encoding='utf8') as f1:
for line in f1: # kiki|123
real_name, real_pwd = line.split('|')
if real_name == username:
print('用户名已经存在,无法注册')
break # 一旦重复 没有必要继续往下校验是否重复了 直接结束循环
else:
with open(r'userinfo.txt', 'a', encoding='utf8') as f2:
f2.write(f'{username}|{password}\n')
print(f'{username}注册成功')
elif choice == '2':
# 1获取用户名和密码
username = input('please input your name>>>:').strip()
password = input('please input your pwd>>>>:').strip()
# 2.读取内容并校验
with open(r'userinfo.txt','r',encoding='utf8') as f2:
for line in f2: # kiki|123\n
real_name, real_pwd = line.split('|') # kiki 123\n
if username == real_name and password == real_pwd.strip('\n'):
print('登录成功')
break
else:
print('用户名或密码错误')
else:
print('编号错误')
标签:文件,encoding,utf8,读写,修改,print,txt,open,光标
From: https://www.cnblogs.com/zhanglanhua/p/16773826.html