python之文件操作:
1.文件操作的初识
文件:联系方式.txt
-
用Python开发一个软件来操作文件,必要参数:
- 文件路径:path
- 编码方式:utf-8,gbk ,gb2312......
- 操作模式:只读,只写,追加,读写,写读......
#示例: f1 = open('d:\联系方式.txt',encoding='utf-8',mode='r')#打开文件,得到文件句柄并赋值给一个变量 content = f1.read() #通过句柄对文件进行操作 print(content) f1.close() #关闭文件
-
代码解释:
open 内置函数,open底层调用的是操作系统的接口。 f1是个变量,被称为文件句柄。常见命名方式:f1,fh,file_handler,f_h。 对文件进行的任何操作,都得通过文件句柄. 的方式。 encoding:声明此次打开文件使用什么编码本。可以不写,不写参数时默认编码本为操作系统默认的编码方式。 (windows: gbk linux: utf-8 mac : utf-8) mode:定义你的操作方式:r为读模式(r模式默认不写)。 f1.close() 关闭文件句柄。
-
文件操作的三部曲:
- 1, 打开文件。
- 2,操作文件,即对文件句柄进行相应操作。
- 3,关闭文件。
-
报错原因:
- UnicodeDecodeError:文件存储时与文件打开时编码本运用不一致。
- 第二个错误: 路径分隔符产生的问题:
- 解决方式:r'C:\Users\oldboy\Desktop\联系方式.txt' 。在路径的整体前面加一个r
-
相对路径与绝对路径:
- 1.绝对路径:从磁盘根目录开始一直到文件名
- 2.相对路径:用一个文件夹下的文件,相对于当前这个程序所在的文件而言。
- 如果在同一个文件中,则相对路径就是这个文件名。 f1 = open('haha',encoding = 'utf-8')
- 如果再上一层文件夹则要使用..\相对路径下,你就可以直接写文件名即可。f1 = open('..\yyy.txt',encoding = 'utf-8',mode = 'r')
2.文件操作的读
r , rb, r+,r+b 四种模式
r模式: 以只读方式打开文件,文件的指针将会放在文件的开头。是文件操作最常用的模式,也是默认模式,如果一个文件不设置mode,那么默认使用r模式操作文件。
read()【重点】** read(n) readline() readlines() for循环读取【重点】 ***
# read() 全部读出来 ** 弊端:如果文件很大就会非常的占用内存,容易导致内存奔溃.
f = open('文件的读', encoding='utf-8') #mode默认为r模式,所以r模式可以默认不写。
content = f.read() #content为字符串类型
print(content,type(content)) #在干嘛 <class 'str'>
f.close()
# read(n) 在r模式下,n按照字符读取。read()读取的时候指定读取到什么位置。文件打开方式为文本模式时,代表读取n个字符。文件打开方式为b模式时,代表读取n个字节
f = open('文件的读', encoding='utf-8')
content = f.read(5)
print(content)
f.close()
# readline() 读取每次只读取一行, 读到的是字符串类型的数据。
注意:readline()读取出来的数据在后面都有一个\n。解决这个问题只需要在我们读取出来的文件后边加一个strip()就OK了。strip()可以去除空格,\n,\t
f = open('文件的读', encoding='utf-8')
print(f.readline()) #读取一行,类型为:字符串
print(f.readline()) #读取一行
print(f.readline())
f.close()
# readlines() 返回一个列表,列表中的每个元素是原文件的每一行。如果文件很大,占内存,容易崩盘。
f1 = open('文件的读',encoding = 'utf-8')
l1 = f1.readlines()
print(l1)#['今天几号eufuhusdujv\n', '现在几点了\n', '你饿了没\n', '老男孩\n'] 列表类型
f1.close()
f = open('文件的读',encoding = 'utf-8')
l1 = f1.readlines()
for line in l1:
print(line)
f1.close()
# 今天几号eufuhusdujv
#
# 现在几点了
#
# 你饿了没
#
# 老男孩
## for循环读取 *** ,
通过对文件句柄进行for循环读取,文件句柄是一个迭代器,文件句柄可以遍历。特点就是每次循环只在内存中占一行的数据,非常节省内存,适合对大文件进行操作。
f = open('文件的读',encoding = 'utf-8')
for line in f1:
print(line)
f.close() #读完的文件句柄一定要关闭
# 今天几号eufuhusdujv
#
# 现在几点了
#
# 你饿了没
#
# 老男孩
rb模式:以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。rb模式也有read read(n)--> n为字节 readline(),readlines() for循环这几种方法
带b的都是以二进制的格式操作文件,他们主要是操作非文本文件:图片,音频,视频等,也可以操作文本文件。
如果你要是带有b的模式操作文件,那么不用声明编码方式。
f = open('美女.jpg',mode='rb') #rb模式打开,不用声明编码方式
content = f.read()
print(content)
f.close()
3.文件操作的写
w,wb, w+,w+b 四种模式
w模式:
# 没有文件,创建文件,写入内容
f = open('文件的写',encoding='utf-8',mode='w')
f.write('随便写一点')
f.close()
# 如果文件存在,先清空原文件内容,再写入新内容
f = open('文件的写',encoding='utf-8',mode='w')
f.write('太白最帅....')
f.close()
wb模式:以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如:图片,音频,视频等。
#以rb的模式将一个图片的内容以bytes类型全部读取出来,然后在以wb将全部读取出来的数据写入一个新文件
f = open('美女.jpg',mode='rb')
content = f.read()
print(content)
f.close() #关闭的是文件句柄,变量content依然存在。
f1 = open('美女2.jpg',mode='wb')
f1.write(content)
f1.close()
w+模式# 写读(自己测试,总结)
f = open('文件的读',encoding='utf-8',mode='w+')
f.write('hello')##写会先清空原文件
f.flush() #保存一下文件
f.seek(0) #让光标回到开头位置,然后再读。否则读到的是空的。
content = f.read()
print(content)
f.close()
# # #w+ 写读测试:
f = open('文件的读',encoding='utf-8',mode='w+')
print(f.tell()) #0 写模式,光标自动从0开始,无论执行了什么操作。
f.seek(0,2) #写读模式,原文件有内容,想光标位置为结尾
print(f.tell())# 0 实际上光标还在开始位置
f.write('hello')##写会先清空原文件。即使修改光标位置还是会清空原文件。
print(f.tell()) # 5
f.flush() #保存一下文件
f.seek(0) #让光标回到开头位置,然后再读。否则读到的是空的。
content = f.read()
print(content)
f.close()
4.文件操作的追加
a, ab, a+,a+b 四种模式
a模式:
# 没有文件,先创建文件,再追加内容
f = open('文件的追加',encoding='utf-8',mode='a')
f.write('太白最帅....')
f.close()
# 有文件,在原文件的最后面追加内容。
f = open('文件的追加',encoding='utf-8',mode='a')
f.write('大壮,舒淇,b哥,雪飞')
f.close()
a+模式:(自己测试,总结)
###a+模式测试: 先写,后读。也可以先读,后写
f = open('文件的读',encoding='utf-8',mode='a+')
f.write('\nhello')##直接在原文件最后面追加内容。\n可以另起一行添加
f.flush() #保存一下文件
f.seek(0) #必须让光标回到开头位置,然后再读。否则读到的是空的。
content = f.read()
print(content)
f.close()
###a+模式测试: 先读,后写。也可以先写后读。
f = open('文件的读',encoding='utf-8',mode='a+')
f.seek(0)#此条可以保证从文件开头开始读
content = f.read()
print(content)
f.write('\nhello')##直接在原文件最后面追加内容。\n可以另起一行添加
f.flush() #保存一下文件
f.close()
5.文件操作的其他模式
#1. 打开文件的模式有(默认为文本模式):
r ,只读模式【默认模式,文件必须存在,不存在则抛出异常】
w,只写模式【不可读;不存在则创建;存在则清空内容】
a, 只追加写模式【不可读;不存在则创建;存在则只追加内容】
#2. 对于非文本文件,我们只能使用b模式,"b"表示以字节的方式操作(而所有文件也都是以字节的形式存储的,使用这种模式无需考虑文本文件的字符编码、图片文件的jgp格式、视频文件的avi格式)
rb
wb
ab
注:以b方式打开时,读取到的内容是字节类型,写入时也需要提供字节类型,不能指定编码
#3,‘+’模式(就是增加了一个功能)
r+, 读写【可读,可写】
w+, 写读【可写,可读】
a+, 写读【可写,可读】
#4,以bytes类型操作的读写,写读,写读模式
r+b, 读写【可读,可写】
w+b, 写读【可写,可读】
a+b, 写读【可写,可读】
r+ 模式:
# 读写模式,先读后写,读并追加 。 注意:顺序不能错误。
f = open('文件的读写', encoding='utf-8', mode='r+')
content = f.read()
print(content)
f.write('人的一切痛苦,本质都是对自己无能的愤怒。')
f.close()
# 错误示例:先写后读
注意:如果你在读写模式下,先写后读,那么文件就会出问题,因为默认光标是在文件的最开始,你要是先写,则写入的内容会讲原内容覆盖掉,直到覆盖到你写完的内容,然后在后面开始读取。
f = open('文件的读写', encoding='utf-8', mode='r+')
f.write('人的一切痛苦,,,本质都是对自己无能的愤怒,,,')
content = f.read()
print(content)
f.close()
#(自)测试修改:
f = open('文件的读', encoding='utf-8', mode='r+')
f.seek(0,2)#把光标位置修改到文件结尾,就可以先写后读。
f.write('人的一切痛苦,,,本质都是对自己无能的愤怒,,,')
content = f.read()
print(content)
f.close()
6.文件操作的其他功能
总结:
三个大方向:
读,四种模式: r rb r+ r+b
写,四种模式 : w,wb, w+,w+b
追加 四种模式: a, ab, a+,a+b
相应的功能:对文件句柄的操作:read() read(n) readline() readlines() write()
# tell 获取光标的位置 单位字节。**
f = open('文件的读写', encoding='utf-8')
print(f.tell())
content = f.read()
print(content)
print(f.tell())
f.close()
# seek 调整光标的位置 ***
seek(n)光标移动到n位置,注意: 移动单位是byte,所有如果是utf-8的中文部分要是3的倍数。
通常我们使用seek都是移动到开头或者结尾,
移动到开头:seek(0), 移动到结尾:seek(0,2)
seek的第二个参数表示的是从哪个位置进行偏移,默认是0,表示开头,1表示当前位置,2表示结尾。
f = open('文件的读写', encoding='utf-8')
f.seek(7)
content = f.read()
print(content)
f.close()
#示例:
f = open("小娃娃", mode="r+", encoding="utf-8")
f.seek(0) # 光标移动到开头,保证可以读到内容
content = f.read() # 读取内容, 此时光标移动到结尾
print(content)
f.seek(0) # 再次将光标移动到开头
f.seek(0, 2) # 将光标移动到结尾
content2 = f.read() # 读取内容. 什么都没有。
print(content2)
f.seek(0) # 移动到开头
f.write("张国荣") # 写入信息. 此时光标在9 中文3 * 3个 = 9
f.flush()
f.close()
# flush 强制刷新 *** 一般写文件时会用,用于强制保存。刷新文件内部缓冲区
f = open('文件的其他功能', encoding='utf-8',mode='w')
f.write('fdshdsjgsdlkjfdf')
f.flush()
f.close()
7.打开文件的另一种方式
# 优点1: 不用手动关闭文件句柄
with open('文件的读',encoding='utf-8') as f1: #等价于:f1 = open('文件的读',encoding='utf-8')
print(f1.read())
# 优点2:一个with语句可以操作多个文件句柄
with open('文件的读', encoding='utf-8') as f1,\ # \ + 回车,程序中换行
open('文件的写', encoding='utf-8', mode='w')as f2:
print(f1.read())
f2.write('hfdsjkghkajhsdjg')
# 缺点:依靠其自动关闭文件句柄,是有一段时间的,这个时间不固定,所以这里就会产生问题,如果你在with语句中通过r模式打开t1文件,那么你在下面又以a模式打开t1文件,此时有可能你第二次打开t1文件时,第一次的文件句柄还没有关闭掉,可能就会出现错误,他的解决方式只能在你第二次打开此文件前,手动关闭上一个文件句柄。
8.文件操作的改【必须会】
- 文件操作改的流程:
1, 以读的模式打开原文件。
2,以写的模式创建一个新文件。
3,将原文件的内容读出来修改成新内容,写入新文件。
4,将原文件删除。
5,将新文件重命名成原文件。 - 具体代码:
# low版:将硬盘存放的该文件的内容全部加载到内存,在内存中是可以修改的,修改完毕后,再由内存覆盖到硬盘
import os
# # 1, 以读的模式打开原文件。
# # 2,以写的模式创建一个新文件。
with open('alex自述',encoding='utf-8') as f1,\
open('alex自述.bak',encoding='utf-8',mode='w') as f2:
# # 3,将原文件的内容读出来修改成新内容,写入新文件。
old_content = f1.read()
new_content = old_content.replace('alex', 'SB')
f2.write(new_content)
os.remove('alex自述')
os.rename('alex自述.bak','alex自述')
# 进阶版:将硬盘存放的该文件的内容一行一行地读入内存,修改完毕就写入新文件,最后用新文件覆盖源文件
import os
# 1, 以读的模式打开原文件。
# 2,以写的模式创建一个新文件。
with open('alex自述',encoding='utf-8') as f1,\
open('alex自述.bak',encoding='utf-8',mode='w') as f2:
# 3,将原文件的内容读出来修改成新内容,写入新文件。
for line in f1:
# 第一次循环 SB是老男孩python发起人,创建人。
new_line = line.replace('SB', 'alex')
f2.write(new_line) #只要文件句柄没关闭,write写就不会清空原文件。
os.remove('alex自述')
os.rename('alex自述.bak','alex自述')
# 有关清空的问题:
# 关闭文件句柄,再次以w模式打开此文件时,才会清空。
with open('文件的写', encoding='utf-8',mode='w') as f1:
for i in range(9):
f1.write('恢复贷款首付款') #只要文件句柄没关闭,write写就不会清空原文件
#自:程序修改,删除文本中的空行
import os
with open('alex自述',encoding='utf-8') as f1,\
open('alex自述.bak',encoding='utf-8',mode='w') as f2:
for line in f1:
if line == '\n': #删除文件的空行
line = line.strip('\n')
f2.write(line)
else:
line = line.replace('alex','SB')
f2.write(line)
os.remove('alex自述')
os.rename('alex自述.bak','alex自述')
#自:跳过空行的方法
# ###########1:
f = open('a',encoding='utf-8')
for line in f:
if line != '\n': #字符串不等于\n,即字符串不是空行
l2 = line.strip().split()#split默认按空格分隔
print(l2)
# #############2:
f = open('a',encoding='utf-8')
for line in f:
l2 = line.strip().split()#split默认按空格分隔
if l2 != []: #空行\n,去除空白后为空字符串,空字符串转换为空列表。不是空列表,即转化之前不是空行
print(l2)
总结:
- 文件操作:【重点】
- r w a rb wb r+ ab 重点记
- read() write tell seek flush
- 文件的改的代码必须会默写。