一、前言
本小节梳理了读写文件的基本用法,介绍了路径的写法、open()函数的用法和with关键字,并准备了图片、音频、视频进行演习操作。
环境说明:Python 3.6、windows11 64位
二、读写文件基本用法
步骤:打开文件>读取文件/写入文件>关闭文件。
# 读
# 打开文件,file1为open()函数调用后返回的文件对象,之后对文件的操作都是对file1对象的操作
file1 = open('f1.txt','r',encoding='utf-8')
# 读取文件
filecontent = file1.read()
print(filecontent)
# 关闭文件
file1.close()
# 写
# 打开文件
file1 = open('f1.txt','w',encoding='utf-8')
# 写入文件
file1.write('Hello world!')
# 关闭文件
file1.close()
注:open()
函数中,第二个参数模式'r'
为只读,'w'
为只写,所以读写要分开。2.1.2介绍更多模式。
2.1 打开文件
2.1.1 文件路径
文件路径的表示方式有两种:绝对路径和相对路径。
绝对路径就是文件的完整路径,在本机的任意Python文件都可正确读取到文件。在网页上,一个完整的网址也是一个绝对路径,在条件允许的情况下,何时何地都可以打开对应的网页。
相对路径就不同,它是一个短路径,是以打开它的Python文件所在目录为基准的路径,如果Python文件和被打开的文件在同一层级目录下,可以直接使用其名字打开文件。一些常用的相对路径的用法:
/
:代表根目录。./
:代表目前所在的目录。../
:代表上一层目录。
例如以下四个路径,他们都是绝对路径,如果用test.py
打开其他三个文件,可以直接使用绝对路径,也可以使用每个路径#
后面的相对路径读取文件。
# 绝对路径
D:/Python/py_file/test.py
D:/Python/py_file/f1.txt # f1.txt
D:/Python/f2.txt # ../f2.txt
D:/Python/py_file/test/f3.txt # ./test/f3.txt
获取路径的方法:
- 方法1:手敲
- 方法2:在资源管理器中,点击地址栏(或
Ctrl+L
),选择地址进行拷贝,需要再加上文件名和后缀 - 方法3:打开命令提示符或终端,按住左键将文件拖到命令提示符或终端松开,复制文件路径
注意:由于\
在Python中是转义符号,使用路径时需要避开转义导致的错误,常用书写路径的方法有三种:
- 使用
\\
转义,表示一个\
,如:"D:\\Python\\py_file\\f1.txt"
- 使用
/
,如:"D:/Python/py_file/f1.txt"
- 使用
r
,如:r"D:\Python\py_file\f1.txt"
2.1.2 open()
open()
用于打开文件,最常用的参数有三个:文件路径、操作文件模式、编码格式。
- 文件路径:参考2.2.1
- 操作文件的模式:
'r'
代表阅读模式,'w'
是写入模式(写入会覆盖掉之前的内容),'a'
是追加写入(不会覆盖掉之前的内容),'rb'
和'wb'
分别表示对二进制文件(视频、音频、图片等)的读取和写入。
基本模式 | b(bytes) | +(读写) | b+ |
---|---|---|---|
r(read),只读,指针在开头,文件不再则报错 | rb,二进制只读 | r+,读写 | rb+,二进制读写 |
w(write),只写,文件不存在则新建,存在则覆盖 | wb,二进制只写 | w+,读写 | wb+,二进制读写 |
a(append),追加,文件存在指针放在末尾,文件不存在则新建 | ab,二进制追加 | a+,追加可读 | ab+,二进制追加 |
- 编码格式: 即返回的数据采用何种编码,一般采用utf-8编码或者gbk编码。
2.2 读和写
2.2.1 read()和write()
read()
用于读取文件,默认读取所有内容,传入整数可指定读取长度,用法:open()对象.read()
,如file1.read()
;
write()
用于写入文件,用法:open()对象.write()
,如file1.write()
。
2.2.2 seek()
关于指针偏移介绍:
可以使用seek()
函数,往括号中传递整数即可偏移位置读取。
语法介绍:seek(offset[,whence])
offset
:偏移量,可以是负值,代表从后向前移动,**该值的计算方式是按字节数,数字和英文及英文标点都是一个字节,中文和中文标点3个字节。**而read(x)
是按字符数。具体后续举例说明。whence
:偏移相对位置,- 为
0
,表示文件起始位置(也可用os.SEEK_SET
表示); - 为
1
,表示文件当前位置(也可用os.SEEK_CUR
表示); - 为
2
,表示文件结尾位置(也可用os.SEEK_END表示)。
- 为
非二进制
seek(x,0)
:表示指针从开头位置移动到x位置,0为默认值,可省略;x必须为完整字符的字节数,具体解释看后文测试代码;seek(0,1)
:表示指针从当前位置开始,只支持0,相当于tell()
,tell()
计算方式也是按字节数;seek(0,2)
:表示指针从文件结尾位置开始,只支持0。
二进制读取支持:
seek(x,0)
:表示指针从开头位置移动到x位置seek(x,1)
:表示指针从当前位置向后移动x个位置seek(-x,2)
:表示指针从文件结尾向前移动x个位置
【非二进制读取操作】
# 写入f1.txt文件
file1 = open('f1.txt','w',encoding='utf-8')
file1.write('我是Xin学数据。')
file1.close()
# 读取文件,非二进制
f = open('f1.txt', 'r',encoding='utf-8')
print(f.read()) # 结果为我是Xin学数据。
f.seek(0) # 读取完指针跑到结尾处,调回文件开头
print(f.tell()) # 结果为0;查看文件指针的位置
# 读取【Xin】
f.seek(6) # 移动6个字节
print(f.tell()) # 结果为6;指针跟随移动6个字节
print(f.read(3)) # 结果为Xin;读取3个字符(3个字节,英文1个字符1个字节)
print(f.tell()) # 结果为9;读取3个字节,指针跟随移动3个字节
# 继续读取3个字符
print(f.read(3)) # 结果为学数据;读取3个字符(9个字节,中文1个字符3个字节)
print(f.tell()) # 结果为18;读取9个字节,指针跟随移动9个字节
# 读取【数据】
f.seek(12)
print(f.read(2))
# 移动到文末
f.seek(0,2)
# 前面提到【x必须为完整字符的字节数】
# 拿该例说明,如果使用f.seek(1)会报错,因为第一个字符【我】有3个字节,3个字节合在一起表示一个中文【我】,如果指针移动一个字节,剩下的两个字节计算机无法解析,所以报错。
# 所以如果要从第二个字符【是】开始读取,应该使用f.seek(3),从第3个字节开始读取(忽略0~2字节,即字符:我)
# f.seek(1) # 报错:UnicodeDecodeError
f.seek(3)
print(f.read()) # 结果为是Xin学数据。
【二进制读取操作】
# 写入f1.txt文件
file1 = open('f1.txt','w',encoding='utf-8')
file1.write('我是Xin学数据。')
file1.close()
# 读取文件,二进制
f = open('f1.txt', 'rb')
print(f.read()) # 结果为b'\xe6\x88\x91\xe6\x98\xafXin\xe5\xad\xa6\xe6\x95\xb0\xe6\x8d\xae\xe3\x80\x82bbb'
f.seek(0) # 读取完指针跑到结尾处,调回文件开头
print(f.tell()) # 结果为0;查看文件指针的位置
# 读取【Xin】
f.seek(6) # 移动6个字节
print(f.tell()) # 结果为6;指针跟随移动6个字节
f.read(3) # 结果为Xin;读取3个字符(3个字节,英文1个字符1个字节)
print(f.tell()) # 结果为9;读取3个字节,指针跟随移动3个字节
# 继续读取3个字符
print(f.read(3)) # 结果为\xe5\xad\xa6;读取3个字符(3个字节),这三个字节表示中文:学
print(f.tell()) # 结果为9;读取9个字节,指针跟随移动9个字节
# 读取【数据】
f.seek(12)
print(f.read(6)) # 返回结果为b'\xe6\x95\xb0\xe6\x8d\xae',中文为:数据
# 在当前位置向后移动2个字符
f.seek(2,1) #
print(f.read(1)) # 结果为b'\x82',可以借助一开始打印的字节码做对照
# 在文末往前9个字符开始取数,读取6个字符
f.seek(-9,2)
print(f.read(6)) # 返回结果为b'\xe6\x95\xb0\xe6\x8d\xae',中文为:数据
# 移动到文末
f.seek(0,2)
2.3 关闭文件
close()
用于关闭文件,用法:open()对象.close()
,如file1.close()
。
作用:
- 释放程序所申请的系统资源;
- 保存文件;
- 增强对文件操作的安全性。
2.4 with关键字
用法:with open() as 变量名 : (注意冒号不能丢!)。
该方法会自动关闭文件,无需close()。
# 读
with open('f1.txt','r',encoding='utf-8') as file1:
filecontent = file1.read()
print(filecontent)
# 写
with open('f1.txt','w',encoding='utf-8') as file1:
file1.write('Hello World!')
三、文件操作示例
说明:以下所有测试文件和python文件都存放在同一个目录下,所以采用相对路径进行操作,你可以拿到文件,打开Python文件运行相关代码。
文件链接:点此直达。文件包含图片、音频、视频、csv文件和python代码文件。
注:需单独观察代码执行效果,注意注释其他代码。
3.1 TXT文件
操作说明:
在目录
D:/Python
下,创建一个文件f1.txt
,写入Hello World!
,然后读取打印。
#################################################################
# TXT文件
#################################################################
# 普通方式
# 写入“Hello World!”
file1 = open('f1.txt','w',encoding='utf-8')
file1.write('Hello world!')
file1.close()
print('写完fi.txt。')
# 读取f1.txt文件并打印
file1 = open('f1.txt','r',encoding='utf-8')
filecontent = file1.read()
file1.close()
print(filecontent)
print('读完fi.txt。')
# with关键字
# 写入“Hello World!”
with open('f1.txt','w',encoding='utf-8') as file1:
file1.write('Hello World!')
print('写完fi.txt。')
# 读取f1.txt文件并打印
with open('f1.txt','r',encoding='utf-8') as file1:
filecontent = file1.read()
print(filecontent)
print('读完fi.txt。')
3.2 二进制文件:图片、音频、视频
读写二进制文件时,不需要传入编码,使用带b
的读写模式。
图片读写,如下图,文件名叫python-logo.png
。
#################################################################
# 图片文件
#################################################################
# 仅用with关键字读写示例
with open('python-logo.png','rb') as file1:
filecontent = file1.read()
print("读完python-logo.png。")
with open('pythonlogo.jpg','wb') as file1:
file1.write(filecontent) # 将上面读取的二进制编码写入
print("写完python-logo.png。")
音频读写,如下:
#################################################################
# 音频文件
#################################################################
# 仅用with关键字读写示例
with open('夜晚虫鸣.wav','rb') as file1:
filecontent = file1.read()
print("读完夜晚虫鸣.wav。")
with open('夜晚虫鸣.mp3','wb') as file1:
file1.write(filecontent) # 将上面读取的二进制编码写入
print("写完夜晚虫鸣.wav。")
视频读写,使用如下两段小视频:
#################################################################
# 视频文件
#################################################################
# 仅用with关键字读写示例
with open('01.ts','rb') as file1:
filecontent_01 = file1.read()
print("读完01.ts。")
with open('02.ts','rb') as file1:
filecontent_02 = file1.read()
print("读完02.ts。")
with open('union.mp4','wb') as file1:
file1.write(filecontent_01)
file1.write(filecontent_02)
print("写完union.mp4。")
3.3 csv文件
csv文件的读写也和TXT文件类似,只是文件后缀名需要改一下即可。
#################################################################
# CSV文件
#################################################################
with open('test_csv.csv','r',encoding='utf-8') as file1:
filecontent = file1.read()
print("读完test_csv.csv。")
with open('test_csv_write.csv','w',encoding='utf-8') as file1:
file1.write(filecontent)
print("写完test_csv.csv。")
通过以上代码独到的数据其实都被处理为文本,如果要取到对应的数据怎么办呢?其实也好处理。下面展示一下将读取到的数据处理为表头和表值,以及{列名:列值}
的形式。
#################################################################
# csv文件处理
#################################################################
with open('test_csv.csv','r',encoding='utf-8') as file1:
filecontent = file1.read()
print("读完")
# print(filecontent)
datas_str = filecontent.split('\n')[:-1] # 按行分割,返回列表,分割完切掉最后的空字符串
datas_list = []
datas_dict = {}
for row in datas_str: # 遍历读取行,每行的数值通过逗号隔开
row_list = row.split(',') # 将每行数据按逗号切割,返回列表
datas_list.append(row_list) # 将切分后的行列表添加到列表
for i in range(len(datas_list[0])):
col = [ls[i] for ls in datas_list]
datas_dict[col[0]] = col[1:] # 将列名和列值按字典格式存储
print(datas_list[0]) # 表头
print(datas_list[1:]) # 表值
print(datas_dict) # 列名:列值
处理为结构化数据之后,更方便做一些处理。但是其实大可不必这么做,直接使用numpy或pandas模块读取csv数据效率更高,以上仅做展示,不推荐。
3.4 word、excel、PDF(含图片的文本)
这几类常见的文件都是通过二进制存储的,读写方式同图片的读写方式。
像word和PDF平常通过Python操作相对比较少,博主了解也甚少,这里不展开;至于Excel一般也推荐通过numpy或pandas进行处理,当然,也可以通过openpyxl。
四、小结
2022-10-15补充:
在读写文件时,还可以通过以下方式,将两种读的方式结合起来
f1 = open('f1.txt','r',encoding='utf-8')
with f1:
print(f1.read())
<下节预告:os文件操作>
- End -