11 文件处理

文件处理

1 文件概述

1.1 什么是文件

文件是操作系统提供给使用者(用户/应用程序)用于操作硬盘的一种虚拟功能/接口。

1.2 为什么需要文件

用户/应用程序可以通过文件将数据永久保存的硬盘中。
用户/应用程序直接操作的对象是文件,对文件进行的所有的操作,都是在向操作系统发送系统调用,然后再由操作系统将这些操作转换成具体的硬盘操作。

2 如何使用文件

文件处理主要使用函数open()
open() 函数用于打开一个文件,并返回文件对象,也称为文件句柄。
open() 函数一般接收两个参数:文件名(file)和模式(mode)

2.1 文件打开模式分类

读写内容和读写操作

2.1.1 控制读写内容的模式: t 和 b

t 和 b 不能单独使用,必须跟 r/w/a 连用
t - 文本(默认)
读写是以str (unicode) 为单位进行的,
只针对文本文件,图片视频等都不适用,
需要指定编码格式参数encoding。
b - bytes (二进制数字)

2.1.2 控制读写操作的模式 r,w,a

r — 只读
w — 只写
a — 只追加写

    • 在模式原有功能的基础上追加其不具备的功能
      r+ — 读 + 写
      w+ — 写 + 读
      a+ — 只追加写 + 读
2.2 操作文件的基本流程
  1. 打开文件
  2. 具体操作:读/写
  3. 关闭文件
2.2.1 打开文件

open(file, mode=‘rt’, encoding=None)
file: 文件路径
mode: 文件打开模式,默认为 rt
encoding: 文件编码,默认为 None
返回文件对象

2.2.2 文件路径
  1. 输入路径时避免转义
open(r'C:\a\b\c.txt')  # rawstring
open('C:/a/b/c.txt')  # 使用 /
  1. 绝对路径:相对于根目录的路径
    相对路径:相对于当前文件的路径
2.2.3 文件编码问题

fileObject.read()
将硬盘中的数据读入内存中。
硬盘上存储的都是二进制数据,read()是将二进制数据读取到内存中
当读取的文件是文本文件时,不能以二进制的格式直接展示给用户。在打开文件时指定参数mode,即以t模式(文本模式)打开文件时,会进行转换。
内存中的字符是以unicode格式存储的。假设读取的文本在硬盘上是以utf-8格式存储的二进制数据,这个转换过程就是将utf-8格式的二进制数据转换为unicode格式的数据。此时就需要指定open()的另一个参数encoding=‘utf-8’。
当以t模式打开文件时,需要指定encoding参数,为文本文件保存时的编码格式,否则可能会出现乱码的问题。

2.2.4 回收资源

打开文件所占用的资源包括两部分:应用程序和操作系统

f = open(r'C:\a\b\c.txt')
  1. 将文件对象交给变量f,占用应用程序的内存空间;
  2. 向操作系统发送请求,要求打开文件,操作系统会在自己的内存空间中分配一部分来维护打开的文件,因此也占用操作系统的内存空间;
  3. 文件对象会对应操作系统打开的文件,通过操作系统映射到硬盘空间上,即应用程序发送系统调用,由操作系统控制硬盘,将内容从硬盘加载到内存中,或者从内存中写入到硬盘上。

回收资源

  1. 回收应用程序的资源::del f
    解除变量名f与内存空间的绑定关系,之后被解释器的垃圾回收机制回收。
  2. 回收操作系统的资源:f.close()
    操作系统同时打开的文件数有上限,因此关闭文件来回收操作系统的资源就十分重要。
2.2.4 上下文管理 with
with open('filepath') as f:
	pass

# 同时打开多个文件 一个with
with open('filepath1') as f1,\
		open('filepath2') as f2:
	pass
2.3 模式详解

t - 文本(默认)

  1. 读写是以str(unicode)为单位进行的,
  2. 只针对文本文件,
  3. 需要指定编码格式参数encoding。
with open('filepath', mode='rt') as f:
	res = f.read()
	f.write('test')

读的过程:
硬盘上存储utf-8格式的二进制数据
将数据从硬盘加载到内存中,t 模式规定读写过程必须是以str(unicode)为单位进行,
因此,t 模式会将 f.read() 读出的结果解码成unicode。
如果不指定编码格式,操作系统不知道以什么编码格式去解码,就以操作系统默认的编码格式解码,可能会出现乱码。
linux/mac: utf-8
windows: gbk

写的过程:
将数据从内存写入到硬盘中,数据在内存中以unicode格式存储,因此需要按照特定的格式编码成二进制数据才能写入硬盘中。
例如encoding=‘utf-8’,将内存中的unicode格式的字符转换为utf-8格式的二进制数据写入硬盘中。

t 模式自动按照指定的编码格式完成编码/解码过程,不需要调用encode()和decode()方法。

r - 只读模式(默认)

with open('filepath', mode='rt', encoding='utf-8') as f:
	res = f.read()
	f.write('test')  # r模式下报错,不可写

文件不存在时会报错
文件存在时文件指针位于文件起始位置
f.read() 会从文件指针所处的位置读取所有内容,直到文件结尾。

with open('filepath', mode='rt', encoding='utf-8') as f:
	res = f.read()
# 重新打开文件,指针位于文件起始位置
with open('filepath', mode='rt', encoding='utf-8') as f:
	res = f.read()  

按行读取文件

with open('filepath', mode='rt', encoding='utf-8') as f:
	for each_line in f:
		print(each_line.strip())  # 去掉'\n'

w - 只写模式
文件不存在时会创建空文件
文件存在时会清空文件,文件指针位于起始位置

with open('filepath', mode='wt', encoding='utf-8') as f:
	res = f.read()  # w模式下报错,不可读
	f.write('test')
	f.write('test')

以w模式打开文件,在没有关闭时可以连续写,新内容会在已存在内容之后继续写入。

a - 只追加写模式

with open('filepath', mode='at', encoding='utf-8') as f:
	res = f.read()  # a模式下报错,不可读
	f.write('test')
	f.write('test')

文件不存在时会创建空文件
文件存在时文件指针位于末尾位置

w 模式与 a 模式的异同:
相同点:在打开的文件不关闭的情况下,两种模式都可以实现连续写入,新写入的内容会跟在已存在内容之后。
不同点:以 a 模式重新打开文件,不会清空原文件内容,会将文件指针直接移动到文件末尾,新写的内容永远写在已存在内容之后。

案例:文本文件拷贝

with open(r'src_filepath', mode='rt', encoding='utf-8') as f1, \
        open(r'dst_filepath', mode='wt', encoding='utf-8') as f2:
    res = f1.read()
    f2.write(res)

+ 模式
可读可写

  • 模式不能单独使用,需要配合 r,w,a
  • 模式取决于原模式,例如 r+ 的限制取决于r,
    r+:文件不存在时报错;
    w+:文件不存在时创建新文件,文件存在时在open()阶段清空文件,即w+模式无法用于读取源文件内容;
    a+:文件不存在时创建新文件,文件存在时文件指针直接移动到文件末尾。对应a/a+模式,写操作都是从末尾追加,此时指针移动无效。

3 练习

3.1 编写文件copy工具

src_path = input('请输入源文件路径').strip()
dst_path = input('请输入目标文件理解:').strip()
with open(r'{}'.format(src_path), mode='rt', encoding='utf-8') as src_file,\
        open(r'{}'.format(dst_path), mode='wt', encoding='utf-8') as dst_file:
    res = src_file.read()
    dst_file.write(src_file)

3.2 编写登录程序,账号密码来自于文件

user_dict = {}
with open('./user_info.txt', mode='rt', encoding='utf-8') as user_file:
    line_list = user_file.read().split()
for each_line in line_list:
    temp_list = each_line.strip().split(':')  # 需要去掉\n
    user_dict[temp_list[0]] = temp_list[1]
un_input = input('请输入用户名:').strip()
pw_input = input('请输入密码:').strip()
if un_input not in user_dict:
    print('用户名不存在。')
elif user_dict[un_input] != pw_input:
    print('输入密码错误。')
else:
    print('登录成功。')

3.3 编写注册程序,账号密码存入文件

un_input = input('请输入用户名:').strip()
pw_input = input('请输入密码:').strip()
with open('./user_info.txt', mode='at', encoding='utf-8') as user_file:
    user_file.write(f'{un_input}:{pw_input}\n')
print('完成注册。')
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值