python基础之文件处理

python基础之文件处理

一、什么是文件

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('没有该功能编号')
posted @ 2022-10-09 19:01  Duosg  阅读(107)  评论(0编辑  收藏  举报