文件操作/模式

今日内容概要

  • 文件操作
  • 文件读写模式
  • 文件诸多方法
  • 文件内光标的移动
  • 文件内光标的移动实战演练
  • 计算机硬盘存取数据的原理
  • 文件内容修改
  • 练习题及答案

1.文件操作

1.文件的概念
    操作系统给用户操作硬盘的快捷方式
    比如我们双击打开一个文件,就是把硬盘中存储的数据加载到内存中
    ctrl+s(保存) 就是将内存中的数据存储到电脑硬盘中
2.代码打开文件的两种方式:
	1.变量名 = open('文件路径','读/写模式',encoding = 'utf8') 
      # 此模式打开后可以正常运行,但是会默认一直开启文件,需要在打一行代码进行关闭
    2.with open('文件路径','读/写模式',encoding = 'utf8') as 变量名:
      # 此模式打开文件后,执行缩进后的子代码完成后会自动关闭文件。
	  # 所以我们在编写代码时一般习惯使用第二种方式方法
3.
'''
文件路径的\符号容易与Python内方法冲突,所以我们在编写文件路径的时候最好在字符串引号前面添加一个r,让路径转义,这样可以避免我们误操作,导致python报错
'''    

2.文件读写模式

1.文件读写模式分为:
 	'r'  # 只读模式,只能读取文件内容,不能进行修改
	'w'  # 只写模式,只能编写内容到文件内,不能看
	'a'  # 追加模式,在文件内容末尾添加信息
	1.'r' 只读模式, 如果文件路径不存在,会直接报错
       with open('b.txt','r',encoding='utf8') as c:
       print(c.read())
    	如果文件存在,就会读取文件内的内容
        with open('a.txt','r',encoding='utf8') as d:
    	print(d.read())
	2.'w'只写模式, 如果文件路径不存在,那么会创建一份新的文件
    	with open('b.txt','w',encoding='utf8') as c:
    	c.write('我是天下第一大帅哥') 
        # 会自动创建一个b.txt文件,并且在文件内写入 '我是天下第一大帅哥'
        '''
        如果需要编写多行,需要自己添加换行符,并且在后续文件对比时也要注意换行符的存在
        w模式每次打开文件会先清空文件内容,然后在进行编写
        '''
    3.'a' 只追加模式,只在文件末尾添加数据,如果文件路径不存在,那么会创建一份新的文件
    	with open('a.txt','a',encoding = 'utf8') as b:
            b.write('是的你真帅')
            # 会在文件内容尾部添加是的你真帅
    4.pass 
	 pass 在python中的作业是为了保持语法结构的完整性
		if 条件:
    		pass (跳过,什么都不做)
    可以跳过需要执行子代码的条件/循环/...等
    		  # pass本身没有意义

3.文件操作模式:

1.文件操作模式
	1. t 文本模式
    	# 文本模式只能对文本类型文件进行操作
        # 必须制定encoding 对应编码
       # 读写是以字符为单位进行
    如上述文件读写操作都是以文本模式进行的操作,我们写读写模式时把t隐藏掉了
    完整的写完应该是:
    with open('a.txt','rt',encoding='utf8') as b:
    在读写模式后面加上t,代表我们所使用的文件操作模式
    2. b 二进制模式
    	# 如果需要使用二进制模式需要在读写模式后面加b,这样就可以代表是二进制模式
        # 可以对任意类型文件进行操作 (计算机本身就可以识别二进制)
        # 读写是以bytes类型为单位
       # 不需要encoding 对应编码
    	二进制模式的写法为:
        with open('a.txt','rb') as c:
    二进制模式,在'r','w','a'模式操作方式与文本模式操作方式一致

4.文件操作方法

1.read()
	只读方法,一次性读取文件内所有内容,并且光标/指针停留在内容末尾。
    文件内容比较多时,如果计算机内存不够读取文件内的数据,就会爆内存
    read()方法中可以填数字参数
    # 在文本模式表示读取几个字符
    # 在二进制模式表示读取几个字节
  	例:
    with open('a.txt','rb') as c:
    print(c.read())  # 读取所有字符
	with open('a.txt', 'r',encoding='utf8') as d:
    print(d.read())  # 读取所有字节
2.readline()
	只读一行方法:只读文件中的一行内容,并且光标/指针会停留在第一行内容末尾
with open('a.txt','r',encoding='utf8') as i:
     print(i.readline())  # 我是天下第一大帅哥
     print(i.readline())  # 是的你真帅
# 注意 我们在二进制模式读取时,他会有\n 换行符进行分割我们在使用readline()方法时要注意
3.readlines()
	读取文件所有内容,并根据每行进行分割  # 每行都有换行符!!
	with open('a.txt','r',encoding='utf8') as i:
    a = i.readlines()
    print(a)  # ['我是天下第一大帅哥\n', '是的你真帅']
    print(type(a))  # <class 'list'>
4.readable()
	判断文件是否可读,返回布尔值
    with open('a.txt','r',encoding='utf8') as i:
    print(i.readable())  # 返回True
5.write()
	写入数据
    with open('a.txt','w',encoding='utf8') as c:
    c.write('天下第一剑神,小白')
    # a.txt 原有内容清空,并输入  '天下第一剑神,小白'
6.writable()
	判断文件是否可写入内容,返回布尔值
    with open('a.txt','w',encoding='utf8') as c:
    print(c.writable())  # True
7.writelines()
	写入一个列表,列表内可写多行内容,换行需要使用换行符隔开
    with open('a.txt','w',encoding='utf8') as c:
    c.writelines(["就是牛 1\n", "还是牛 2"])  # 就是牛 1 还是牛 2
8.flush()
	用来刷新缓冲区的,即将缓冲区中的数据立刻写入文件,同时清空缓冲区,不需要是被动的等待输出缓冲区写入。
    相当于ctrl + S 保存功能
9.for循环
	for循环也可用于文件读取
    在读取文件时就可以一行一行的遍历出来,这样可以避免read()方法内存容纳不下被爆掉
10.文件内光标移动
    1.seek()
        seek方法可以用于移动文件读取指针/光标到指定位置。
        ()内参数为:
            offset,whence
          开始的偏移量  哪里(模式0,1,2) # 模式0 从头开始 模式1,从当前光标所处位置开始 模式2 从末尾开始
        with open('a.txt','rb') as c:
        c.seek(3,0)  # c.write('让我康康你的脸') 因为中文是三个字节
        print(c.read(6).decode('utf8'))  # read(6)读取偏移量0后6个字节并转码utf-8 我康
        c.seek(-9,2)  # 倒着取
        print(c.read(9).decode('utf8'))  # 你的脸
        whence参数 1,2 模式只支持b(二进制模式)使用,0模式t,b模式都可以使用
		# 偏移量只能是字节,不支持字符
	2.tell()
    	tell 方法可以查询当前光标/指针所处位置 # 文本模式是字符,二进制模式是字节
            a = c.tell()
    		print(a)  # 9
	

5.文件内光标移动实战操作


光标移动也有实际的应用场景:
import time  # 导入模块(时间)

with open(r'a.txt', 'rb') as f: # 打开文件,模式read
    f.seek(0, 2)  # seek()方法 偏移量0 whence 2光标移动到文件末尾处
    while True:
        line = f.readline()  # 一行一行读取数据赋值给变量Line
        if len(line) == 0:  # 如果 line 的长度为0
           
            time.sleep(0.5)  # 放慢0.5秒后执行
        else:
            print(line.decode('utf8'), end='') # 打印光标末尾处 新增的内容
            
 '''
 此功能是一个小监控功能,可以读取文件内新录入的内容,并打印出来
 '''

6.计算机硬盘修改数据的原理

1.硬盘记录数据的原理
	硬盘读写数据我们可以看成在纸上记录数据,当我们需要修改中间位置内容时,就需要重新写字,写过的字不能冲中间分开它们
2.硬盘删除数据的原理
	不是直接拿橡皮擦擦除纸上内容,而是改变它的状态,等待后续的文字内容覆盖它
    简单的说,硬盘在保存文件时,一般会按照“簇”的形式将数据进行保存,至于保存的文件默认会记录在文件分配表中。而硬盘删除文件时,系统也不会把它所存储的文件全部清空,而是将之前在各个分配表中的“簇”标记为空显示。文件分配表里面还有哪个“簇”没有使用,后期所存储的数据也就会存入该簇中。所以在数据重新写入之前,这些删除的文件依然会存在之前所在的“簇”中,直到新数据的写入,覆盖原有数据。
    我们一旦覆盖了原来已经改变状态了的区域,那么我们就无法在进行恢复了,此数据一定会丢失,无法在恢复
    # 当然这是机械硬盘的原理,固态硬盘原理是由算法构成,所以就不存在恢复信息,或者由的固态硬盘会单独构建一块存储区域专供数据恢复的

7.文件内容修改

1.文件内部修改信息其实就由上述计算机硬盘修改数据的原理一致
方式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('a.txt', 'r', encoding='utf8') as read_f, \
        open('.a.txt.swap', 'w', encoding='utf-8') as write_f:
    for line in read_f:
        write_f.write(line.replace('tony', 'kevinSB'))
os.remove('a.txt')  # 删除a.txt
os.rename('.a.txt.swap', 'a.txt')  # 重命名文件

8.练习题及答案

1.编写简易版本的拷贝工具
     自己输入想要拷贝的数据路径 自己输入拷贝到哪个地方的目标路径
     任何类型数据皆可拷贝
     ps:个别电脑C盘文件由于权限问题可能无法拷贝 换其他盘尝试即可
solution:1
        location = input('请输入您想要拷贝的数据路径>>>>>>:')
target_location = input('请输入您的目标数据路径>>>>>>:')
with open(r'{}'.format(location),'rb') as data:  # 打开想要拷贝的数据路径地址
    data1 = data.read()  # 获取读取的值复制给Data1
    location1 = location.split('\\')
    for b in location1:
        if '.' in b:
            data2 = b
            with open(r'{}\{}'.format(target_location,data2),'wb') as target_data: # 打开目标拷贝地址
                target_data.write(data1)  # 写入 data1
                print('拷贝成功哦,就是牛')
				
				
solution:2
# 1.先获取用户输入信息
want_file_path = input('请输入您想要拷贝的文件路径>>>>>:')
target_file_path = input('请输入您的目标路径>>>>>>:')
# 打开文件读取所有内容
with open(r'{}'.format(want_file_path), 'rb') as file_read, open(r'{}'.format(target_file_path), 'wb') as file_write:
    for data in file_read:  # 遍历每一行读取的内容
        file_write.write(data)  # 把遍历的内容写进目标位置的新文件内部
		
		
2.利用文件充当数据库编写用户登录、注册功能
  文件名称:userinfo.txt
  基础要求:
  		 用户注册功能>>>:文件内添加用户数据(用户名、密码等)
       用户登录功能>>>:读取文件内用户数据做校验
      ps:上述功能只需要实现一次就算过关(单用户) 文件内始终就一个用户信息
        while True:
    print('欢迎光临随风登录系统'
              '1.用户注册:'
              '2.用户登录')
    choice = input('请输入您想要选择功能>>>>>>:')
    if choice.strip() == '1':
        print('用户注册')
        with open('userinfo.txt','w',encoding='utf8') as data:
            username = input('请输入您的用户名>>>>>:')
            password = input('请输入您的密码>>>>>:')
            data.writelines(f'{username},{password}\n')
            print(f'{username}注册成功')
    if choice.strip() == '2':
        print('用户登录')
        target_username = input('请输入用户名>>>>>:')
        target_password = input('请输入密码>>>>>>:')
        with open('userinfo.txt', 'r', encoding='utf8') as data1:
            b = data1.readlines()
            for x in b:
                if target_username in x and target_password in x:
                    print(f'{target_username}登录成功')
                else:
                    print('用户名或密码输入错误')
  拔高要求:
       用户可以连续注册
      用户可以多账号切换登录(多用户)  文件内有多个用户信息
      ps:思考多用户数据情况下如何组织文件内数据结构较为简单
    提示:本质其实就是昨天作业的第二道题 只不过数据库由数据类型变成文件
solution:1
        while True:
    print('欢迎光临随风登录系统'
              '1.用户注册:'
              '2.用户登录')
    choice = input('请输入您想要选择功能>>>>>>:')
    if choice.strip() == '1':
        print('用户注册')
        with open('userinfo.txt','a',encoding='utf8') as data:
            username = input('请输入您的用户名>>>>>:')
            password = input('请输入您的密码>>>>>:')
            data.writelines(f'{username},{password}\n')
            print(f'{username}注册成功')
    if choice.strip() == '2':
        print('用户登录')
        target_username = input('请输入用户名>>>>>:')
        target_password = input('请输入密码>>>>>>:')
        with open('userinfo.txt', 'r', encoding='utf8') as data1:
            b = data1.readlines()
            for x in b:
                if target_username in x and target_password in x:
                    print(f'{target_username}登录成功')
                else:
                    print('用户名或密码输入错误')
					
solution:2
while True:
    print('请您根据提示输入指令\n'
          '1.用户注册'
          '2.用户登录'
          '3.退出程序(Q)')
    choice = input('请输入您想执行的功能编号>>>>>:').strip()
    if choice == '1':
        username = input('请输入您想要注册的用户名>>>>>:').strip()
        with open(r'userinfo.txt', 'r', encoding='utf8') as data_read:
            for real_data in data_read:
                if username == real_data:
                    print('用户名已经存在,请重新注册')
                    break
            else:
                password = input('请输入你想设置的密码>>>>>:').strip()
                with open(r'userinfo.txt', 'w', encoding='utf8') as data_file:
                    data_file.write(f'{username}|{password}')
                    print(f'恭喜{username}注册成功,允许登录')
    elif choice == '2':
        username = input('请输入您的用户名>>>>>:').strip()
        password = input('请输入您的密码>>>>>:').strip()
        with open(r'userinfo.txt', 'r', encoding='utf8') as data_read:
            for real_data in data_read:
                real_username, real_password = real_data.split('|')
                if real_password == password and real_username == username:
                    print('登录成功')
                    break
                else:
                    print('请输入正确的用户名或密码')
    elif choice.upper() == 'Q':
        print('程序结束')
        break
    else:
        print('请输入正确编号')
		
		注意:此功能并不完善,solution2 必须是在已经有userinfo.txt文件并且里面有数据才可允许
		                  而solution1 里面无法判断用户名是否重复!!!
posted @ 2022-10-08 23:36  dd随风  阅读(51)  评论(0编辑  收藏  举报