引言
最常用的文件存储文件格式:txt、csv
-
到目前为止,我们做的一切操作,都是在内存里进行的,这样会有什么问题吗?如果一旦断电或发生意外关机了,那么你辛勤的工作成果将瞬间消失。是不是感觉事还挺大的呢?现在你是否感觉你的编程技巧还缺了点什么呢?是的,我们还缺少将数据在本地文件系统进行持久化存储的能力,白话讲就是文件的读写能力。
文件新建
x,新建(特殊的写入方式)。如果文件存在则报错,如果不存在就新建文件,然后写入内容,比w模式更安全,不会清空已经存在的文件的内容。
fp = open('hello.txt', 'x') # 新建文件,然后写入内容
fp.write('hello Tom and jay') # 表示往新建的文件fp里写入内容为'hello Tom and jay!'
fp.close() # 关闭文件fp。
文件打开
语法:f = open(filename, mode)
fp = open('hello.txt', 默认为'r'也可以是'w'或'a'或'x'或'b'或'+') # 打开文件,open函数会返回一个文件句柄/文件描述符(如fp),文件句柄/文件描述符表示所打开的文件(如open('hello.txt', 'w'))
-
Python内置了一个open()方法,用于对文件进行读写操作。使用open()方法操作文件就像把大象塞进冰箱一样,可以分三步走,一是打开文件,二是操作文件,三是关闭文件。
-
文件句柄/文件描述符
-
open()方法的返回值是一个file对象,可以将它赋值给一个变量,这个变量就是所谓的文件句柄(以前叫文件描述符)。
-
file对象:
-
可以调用read()和write()方法,对打开的文件进行读写操作。
-
-
-
open方法的语法
-
f = open(filename, mode)
-
f = open(filename, mode,encoding='UTF-8')
-
filename:
-
一个包含了你要访问的文件名称的字符串值,通常是一个文件路径。
-
文件路径作用:定位到指定文件
-
-
mode:
-
打开文件的模式(权限),有很多种,默认是只读方式r。
-
-
-
-
文件打开的模式:
-
编辑
fp = open('hello.txt', 'w') # 打开文件,open函数会返回一个文件句柄/文件描述符(如fp),文件句柄/文件描述符表示所打开的文件(如open('hello.txt', 'w')) fp.write('hello Tom and jay') # 通过文件句柄fp调用write函数。表示往打开的文件fp里写入内容为'hello Tom and jay!' fp.close() # 关闭文件fp。
文件写入
w,只写。如果文件不存在,新建文件然后写入;如果存在,先清空文件内容,再写入。不安全的写入方式,会清空原来的内容。
fp.write('内容'),调用写入操作的方法,对打开的文件进行写入操作
-
fp.write('hello Tom and jay') # 表示往打开的文件fp里写入内容为'hello Tom and jay!'
文件关闭
fp.close() # 关闭文件fp。
文件读取
r,只读。默认模式,如果文件不存在就报错,存在就正常读取。
fp.read() # 调用读取操作的方法,对打开的文件进行读取操作。read 读取文件里所有的数据;
fp.readlines() # 调用读取操作的方法,对打开的文件进行读取操作。read 读取文件里每行数据,并返回成一个列表;
text = fp.readline() # 调用读取操作的方法,对打开的文件进行读取操作。 read 读取文件里第一行数据
-
fp = open('hello.txt', 'r') text = fp.read() # read 读取文件里所有的数据,返回: # Hello Tom and jay # Hwo are you? # Fine, and you ? # I'm fine too,thank you ! print(text) fp.close() fp = open('hello.txt', 'r') text = fp.read(7) # read 读取文件里指字符数(如7个字符)的数据,返回:Hello T print(text) fp.close() fp = open('hello.txt', 'r') text = fp.readlines() # read 读取文件里每行数据,并返回成一个列表['Hello Tom and jay\n', 'Hwo are you?\n','Fine, and you ?\n', "I'm fine too,thank you !"] print(text) fp.close() fp = open('hello.txt', 'r') text = fp.readline() # # read 读取文件里第一行数据,返回:Hello Tom and jay print(text) fp.close()
文件追加
a,追加(特殊的写入方式)。如果文件不存在,新建文件,然后写入;如果存在,在文件的最后追加写入。
-
fp = open('hello.txt', 'a') # 打开文件 fp.write('hello Tom and jay') # 表示往打开的文件fp里追加写入内容为'hello Tom and jay!' fp.close() # 关闭文件fp。
-
常规文件打开模式操作演示
-
b模式:
-
二进制模式,通常用来读取图片、视频等二进制文件。注意,它在读写的时候是以bytes类型读写的,因此获得的是一个bytes对象而不是字符串。在这个读写过程中,需要自己指定编码格式。在使用带b的模式时一定要注意传入的数据类型,确保为bytes类型。
-
-
+模式:
对于w+模式,在读写之前都会清空文件的内容。
对于a+模式,永远只能在文件的末尾写入。
对于r+模式,也就是读写模式。
-
对于w+模式,在读写之前都会清空文件的内容。 对于a+模式,永远只能在文件的末尾写入。 对于r+模式,也就是读写模式。 fp = open('hello.txt', 'w+') text = fp.write('hello my python!') # 写如之前会清空文件的内容 print(text) # 返回的是写入的字符个数 fp.close() fp = open('hello.txt', 'r+') text = fp.read(6) # 读写模式 print(text) # 返回的是读取的内容 fp.close() fp = open('hello.txt', 'r+') text = fp.write('my python!') # 覆盖之前文件的内容 print(text) # 返回的是写入的字符个数 fp.close() fp = open('hello.txt', 'a+') fp.write('\n这句话会添加在之前写入的内容之后') fp.seek(0) # 通过seek方法可以将光标调整到0,括号内的数字表示从第几个字符后读取。 text = fp.read() # 如果是读取模式,需要结合调整光标位置来实现。 # fp.seek(0) # 通过seek方法可以将光标调整到0 print(fp.tell()) # 通过tell方法可以查到当前的光标所在位置,返回的数字代表光标后有几个字符 print(text) # 返回的是写入的字符个数 fp.close()
-
编码问题
-
要读取非UTF-8编码的文件,需要给open()函数传入encoding参数,例如,读取GBK编码的文件
-
遇到有些编码不规范的文件,可能会抛出UnicodeDecodeError异常,这表示在文件中可能夹杂了一些非法编码的字符。遇到这种情况,可以提供errors=’ignore‘参数,表示如果遇到编码错误后如何处理。
-
-
文件对象操作
-
每当我们用open方法打开一个文件时,将返回一个文件对象。这个对象内置了很多操作方法。
-
f.read(size) #size读取数据的个数
-
读取一定大小的数据, 然后作为字符串或字节对象返回。size是一个可选的数字类型的参数,用于指定读取的数据量。当size被忽略了或者为负值,那么该文件的所有内容都将被读取并且返回。
-
注意:
-
如果文件体积较大,请不要使用read()方法一次性读入内存,而是read(512)这种一点一点的读。
-
-
-
f.readline()
-
从文件中读取一行n内容。换行符为'\n'。如果返回一个空字符串,说明已经已经读取到最后一行。这种方法,通常是读一行,处理一行,并且不能回头,只能前进,读过的行不能再读了。
-
-
f.readlines()
-
将文件中所有的行,一行一行全部读入一个列表内,按顺序一个一个作为列表的元素,并返回这个列表。readlines方法会一次性将文件全部读入内存,所以也存在一定的风险。但是它有个好处,每行都保存在列表里,可以随意存取。
-
-
#需求:读取文件中的数据 fp = open('./test.txt','r') text = fp.read(10) #读取指定字节的数据 text_line = fp.readline() #一次读取一行数据 text_lines = fp.readlines() #读取多行数据,返回一个列表 print(text_lines) fp.close()
-
总结:
-
几种不同的读取和遍历文件的方法比较:如果文件很小,read()一次性读取最方便;如果不能确定文件大小,反复调用read(size)比较保险;如果是配置文件,调用readlines()最方便。普通情况,使用for循环更好,速度更快。
-
-
f.write()
-
将字符串或bytes类型的数据写入文件内。write()动作可以多次重复进行,其实都是在内存中的操作,并不会立刻写回硬盘,直到执行close()方法后,才会将所有的写入操作反映到硬盘上。在这过程中,如果想将内存中的修改,立刻保存到硬盘上,可以使用f.flush()方法。
fp = open('./test123.txt','w') fp.write('hello Tom ') fp.close() #将文件内容清空,再写入新数据
fp = open('./test123.txt','a') fp.write('hello Tom ') fp.close() #在文件数据末尾追加数据
-
-
f.close()
-
关闭文件对象。当处理完一个文件后,调用f.close()来关闭文件并释放系统的资源。文件关闭后,如果尝试再次调用该文件对象,则会抛出异常。忘记调用close()的后果是数据可能只写了一部分到磁盘,剩下的丢失了,或者更糟糕的结果。也就是说大象塞进冰箱后,一定不要忘记关上冰箱的门。
-
-
-
with关键字
with关键字用于Python的上下文管理器机制。为了防止诸如open这一类文件打开方法在操作过程出现异常或错误,或者最后忘了执行close方法,文件非正常关闭等可能导致文件泄露、破坏的问题。Python提供了with这个上下文管理器机制,保证文件会被正常关闭。在它的管理下,不需要再写close语句。注意缩进。
with open('./test123.txt','r') as fp: #fp = open() text = fp.read(5) print(text) #上下两组代码功效一样 fp = open('./test123.txt','r') text = fp.read(5) print(text) fp.close()
对图片,音频,视频,压缩包等二进制的数据进行文件读写操作
-
实现一个图片文件的拷贝
-
1.打开一个图片文件,读取其二进制的数据
-
2.将读取到的数据写入到另一个路径下
-
过程:1.打开图片;2.读取图片二进制的数据;3.将读取到的图片数据写入到另一个文件中;4.关闭文件
fp = open('feilong.png', 'rb') # r是读取文本数据,rb是读取二进制数据
img_data = fp.read() # 读取到了图片的二进制数据
# 将图片的二进制数据写到另一个路径下
fp1 = open('./imgs/fei.jpg', 'wb') # ./imgs/fei.jpg是相对路径
fp1.write(img_data)
fp.close()
fp1.close()
fp = open('D:/feilong.png', 'rb') # r是读取文本数据,rb是读取二进制数据。D:/feilong.png是绝对路径
img_data = fp.read() # 读取到了图片的二进制数据。
# 将图片的二进制数据写到另一个路径下
fp1 = open('D:/study/fei.jpg', 'wb') # D:/study/fei.jpg是绝对路径
fp1.write(img_data)
fp.close()
fp1.close()
将上面的代码封装成函数
def imgCopy(img, copyImg): # img是原始图片地址的形参,copyImg是新图片地址的形参
# 1.打开原始图片img
fp = open('D:/feilong.png', 'rb') # r是读取文本数据,rb是读取二进制数据
# 2.读取原始图片的二进制数据
img_data = fp.read() # 读取到了图片的二进制数据.D:/feilong.png是绝对路径
# 3.将读取到的图片数据写入到另一个新的图片文件中
# 将图片的二进制数据写到另一个路径下
fp1 = open('D:/study/fei.jpg', 'wb') # D:/study/fei.jpg是绝对路径
fp1.write(img_data)
# 4.关闭文件
fp.close()
fp1.close()
imgCopy('D:/feilong.png', 'D:/study/fei.jpg') # 调用函数imgCopy并进行传参
# 实现一个图片复制功能(图片数据就是二进制类型的数据)
# 过程:1.打开图片 2.读取图片二进制的数据 3.将读取到的图片数据写入到另一个文件中 4.关闭文件
def imgCopy(img,copyImg): #img是原始图片路径 copyImg是复制的图片路径
# 1.打开原始图片img
fp_1 = open(img,'rb')
# 2.读取原始图片的二进制数据
img_data = fp_1.read()
# 3.将读取到的图片数据写入到另一个新的图片文件中
fp_2 = open(copyImg,'wb')
fp_2.write(img_data)
# 4.关闭文件
fp_1.close()
fp_2.close()
imgCopy('pandas.jpg','./imgs/new_pandas.jpg')
练习:登录注册
'''
需求:注册功能
1.让用户录入用户名,密码,重复密码,手机号基本信息
2.检测两次输入的密码是否一致,一致则注册成功,否则注册失败
3.注册成功后需要将用户信息存储到文件中进行保存
'''
def regist():
#让用户录入用户名,密码,重复密码,手机号基本信息
print('------欢迎来到注册页面--------')
username = input('输入注册的账号:')
password = input('输入注册的密码:')
repeatpwd = input('重复密码:')
phonenum = input('手机号:')
#检测两次输入的密码是否一致,一致则注册成功,否则注册失败
if password == repeatpwd:#==可以判断两个字符串是否一样:
#两次密码一致:注册成功,将用户信息写入到文件保存
with open('userData.txt','a+') as fp:
#\n表示回车换行的意思
fp.write(username+'-'+password+'-'+phonenum+'\n')
print('恭喜您注册成功,账号为:',username)
else:#两次密码不一致,注册失败
print('两次密码不一致,注册失败,请重新注册!')
'''
登录功能:
1.让用户录入用户名,密码
2.验证登录状态
'''
def login():
#1.让用户录入用户名,密码
print('------欢迎来到登录页面------')
username = input('请输入登录的账号:')
password = input('请输入登录的密码:')
#2,验证登录状态
#读取文件中的用户信息的数据
with open('userData.txt','r') as fp:
#[Tom -123-222, jay-456-666]
user_data_list = fp.readlines() #读取每一行数据,返回的是一个列表
for data in user_data_list:
data = data.strip()#取出字符串中的回车
#切分字符串,取出用户名和密码即可
#s_data = [Tom ,123,222]
s_data = data.split('-')
#从文件中获取的用户名和密码
f_username = s_data[0]
f_password = s_data[1]
#判断登录状态
flat = 0 #如果flat=0表示登录失败,为1表示登录成功
if username == f_username and password == f_password:
flat = 1 #表示登录成功
break
if flat == 1:
print('登录成功')
else:
print('登录失败')
login()
# regist()#调用该函数完成注册功能