Python(6): 文件及IO操作
1 文件
1.1 概述
- 存储在计算机的存储设备中的一组数据序列就是文件。
- 不同类型的文件通过后缀名进行区分。
- 在Python中,文件被分为两类:①文本文件;②二进制文件。
1.2 文件的基本操作
打开/创建文件:
name=open(filename,mode,encoding)
filename
: 文件名mode
: 打开模式(详见下表)打开模式 说明 r 以只读模式打开,文件指针在文件的开头,如果文件不存在,程序抛异常 rb 以只读模式打开二进制文件,如图片文件 w 覆盖写模式,文件不存在创建,文件存在则内容覆盖 wb 覆盖写模式写入二进制数据,文件不存在创建,文件存在则内容覆盖 a 追加写模式,文件不存在创建,文件存在则在文件最后追加内容 + 与w/r/a等一同使用,在原功能基础上增加同时读写功能 encoding
: 编码模式- 若文件名在目录中未创建,则会自动创建一个文件,不会报错。
操作文件:
- ①
name.read()
只读 ②
name.write(s)
覆盖写入读写方法 说明 file.read(size) 读取指定字节的字符,若无参数则读取全部,结果为字符串类型 括号中为所读取字符数,而非字节大小 file.readline(size) 读取一行数据,若给定参数,则读取改行指定字节的字符,结果为字符串类型 file.readlines() 读取全部内容,结果为列表类型 file.write(s) 将字符串s写入文件 file.writelines(lst) 将内容全部为字符串的列表lst写入文件 file.seek(offset) 改变文件操作指针的位置 注:指针默认位置为文档首端,括号中为字节大小 (英文=1B,中文GBK编码=2B,UTF-8编码=3B)
- ①
- 关闭文件:
name.close()
1.2.1 例11.1:文件的基本读写
def my_write(): # 定义函数
# (1)(创建)打开文件
file=open('a.txt','w',encoding='utf-8')
# (2)操作文件
file.write('The Great Chinese Dream')
# (3)关闭文件
file.close()
# 读取
def my_read():
file=open('a.txt','r',encoding='utf-8')
s=file.read()
print(type(s),s)
file.close()
# 主程序运行
if __name__ == '__main__':
my_write() # 调用函数
my_read()
1.2.2 例11.2:文件的写入操作
def my_write(s):
file=open('b.txt','a',encoding='utf-8')
file.write(s)
file.write('\n')
file.close()
def my_write_list(file,lst):
f=open(file,'a',encoding='utf-8')
f.writelines(lst)
f.close
if __name__ == '__main__':
my_write('伟大的中国梦')
my_write('北京欢迎您')
my_write_list('c.txt',['姓名\t','年龄\t','成绩\n','张三\t','30\t','98'])
1.2.3 例11.3:文件的读取操作
1.2.3.1 全部读取(第7行)
def my_read(filename):
file=open(filename,'w+',encoding='utf-8')
# 'w+'兼备写入和读取功能
file.write('你好啊') # 写入完成,指针在最后
file.seek(0) # 把指针置于最前端
# 读取
s=file.read() # 读取全部
print(type(s),s)
file.close()
if __name__ == '__main__':
my_read('d.txt')
1.2.3.2 读取指定字符数(第7行)
def my_read(filename):
file=open(filename,'w+',encoding='utf-8')
# 'w+'兼备写入和读取功能
file.write('你好啊') # 写入完成,指针在最后
file.seek(0) # 把指针置于最前端
# 读取
s=file.read(2) # 2指的是两个字符,而非字节
print(type(s),s)
file.close()
if __name__ == '__main__':
my_read('d.txt')
1.2.3.3 读取一行数据(第7行)
def my_read(filename):
file=open(filename,'w+',encoding='utf-8')
# 'w+'兼备写入和读取功能
file.write('你好啊') # 写入完成,指针在最后
file.seek(0) # 把指针置于最前端
# 读取
s=file.readline() # 读取一行数据
print(type(s),s)
file.close()
if __name__ == '__main__':
my_read('d.txt')
1.2.3.4 读取一行数据的指定个字符(第7行)
def my_read(filename):
file=open(filename,'w+',encoding='utf-8')
# 'w+'兼备写入和读取功能
file.write('你好啊') # 写入完成,指针在最后
file.seek(0) # 把指针置于最前端
# 读取
s=file.readline(2) # 读取一行数据的两个字符
print(type(s),s)
file.close()
if __name__ == '__main__':
my_read('d.txt')
1.2.3.5 读取所有行(第7行)
注意:与以上不同,readlines()
括号中的数字表示行数,输出为列表类型。
def my_read(filename):
file=open(filename,'w+',encoding='utf-8')
# 'w+'兼备写入和读取功能
file.write('你好啊') # 写入完成,指针在最后
file.seek(0) # 把指针置于最前端
# 读取
s=file.readlines() # 读取所有行数据
print(type(s),s)
file.close()
if __name__ == '__main__':
my_read('d.txt')
1.2.3.6 通过移动指针读取部分内容(第5行)
def my_read(filename):
file=open(filename,'w+',encoding='utf-8')
# 'w+'兼备写入和读取功能
file.write('你好啊') # 写入完成,指针在最后
file.seek(3) # 把指针置于第一个字后,即3个字节后
s=file.read()
print(type(s),s)
file.close()
if __name__ == '__main__':
my_read('d.txt')
1.2.4 例11.4:文件复制(图片为例)
def copy(src,npath):
# 文件的复制就是“边读边写”操作
file1=open(src,'rb')
file2=open(npath,'wb')
s=file1.read() # 先读取file1,把s赋值为file1
file2.write(s) # 执行写入操作,把s写入file2
file2.close()
file1.close() # 先打开的后关闭,后打开的先关闭
if __name__ == '__main__':
src='./arc.png' # “./”一点一杠代表当前路径
npath='../chap/copy_arc.png' # “../”两点一杠代表上级目录,即等效于后退一步
copy(src,npath)
print('文件复制完毕')
1.3 文件的状态和操作过程
- 存储状态:文件在磁盘上未被打开的状态。
- 占用状态:文件被
open()
打开后进入占用状态,此时文件不允许其他程序进行操作,需要close()
将其关闭才能回到可操作状态。
2 with语句
2.1 定义
又称上下文管理器(context manager),在处理文件时,无论是否产生异常,都能保证with语句执行完毕后关闭已经打开的文件,这个过程是自动的,无需手动操作。
2.2 语法结构
with open(...)as file:
pass
2.3 例11.5:with语句
def write_fun():
# 打开文件 aa.txt 以写入模式,并确保在操作完成后关闭文件
with open('aa.txt', 'w', encoding='utf-8') as file:
# 写入内容到文件
file.write('2022北京冬奥会欢迎您')
def read_fun():
# 打开文件 aa.txt 以读取模式,并确保在操作完成后关闭文件
with open('aa.txt', 'r', encoding='utf-8') as file:
# 读取文件内容并打印
print(file.read())
def copy(src_file, target_file):
# 打开源文件以读取模式,并确保在操作完成后关闭文件
with open(src_file, 'r', encoding='utf-8') as file:
# 打开目标文件以写入模式,并确保在操作完成后关闭文件
with open(target_file, 'w', encoding='utf-8') as file2:
# 读取源文件内容并写入目标文件
file2.write(file.read())
if __name__ == '__main__':
# 调用写入函数
write_fun()
# 调用读取函数
read_fun()
# 调用复制函数
copy('./aa.txt', './dd.txt')
3 数据的组织维度及存储
3.1 定义
- 数据的组织维度,也称为数据的组织方式或存储方式,在Python中常用的数据组织方式可分为一维数据、二维数据和高维数据。
- 一维数据:通常采用线性方式组织数据,一般使用Python中的列表、元组或者集合进行数据的存储。
- 二维数据:也称表格数据,由行和列组成,类似于Excel表格,在Python中使用二维列表进行存储。
- 高维数据:使用键值对(key-value pair)方式组织数据,并借助字典形式存储。在Python中内置的json模块专门用来处理JSON(JavaScript Object Notation)格式的数据。
3.2 高维数据JSON模块的常用函数
函数名称 | 说明 |
---|---|
json.dumps(obj) | 将Python数据类型转成JSON格式过程,编码过程 |
json.loads(s) | 将JSON格式字符串转成Python数据类型,解码过程 |
json.dump(obj,file) | 与dumps() 功能相同,将转换结果存储到file中 |
json.load(file) | 与loads() 功能相同,从file中读入数据 |
3.3 例11.6:一维和二维数据的存储
def my_write():
# 定义一个包含一维数据的列表
lst = ['adx', 'wmc', 2024, 39]
# 打开文件 'mai.csv' 以写模式 ('w') 打开,如果文件不存在将创建文件
with open('mai.csv', 'w') as file1:
# 使用 join() 方法将列表元素转换为字符串,并用逗号连接每个元素
file1.write(','.join(lst))
# join() 用于将列表元素转为字符串,用逗号拼接元素
def my_read():
# 打开文件 'mai.csv' 以读模式 ('r') 打开
with open('mai.csv', 'r') as file1:
# 读取文件内容并存储到字符串变量 s 中
s = file1.read()
# 使用 split() 方法将字符串转换为列表,分隔符为逗号
lst = s.split(',')
# 打印列表
print(lst)
# 存储和读取二维数据
def my_write_table():
# 定义一个包含二维数据的列表
lst = [
['商品名', '单价', '采购数量'],
['adx controller', '10888', '1'],
['yuangeki', '1500', '2']
]
# 打开文件 'wmcshopping.csv' 以写模式 ('w') 打开,并指定编码为 'utf-8'
with open('wmcshopping.csv', 'w', encoding='utf-8') as file2:
# 遍历列表中的每个子列表
for item in lst:
# 使用 join() 方法将子列表元素转换为字符串,并用逗号连接每个元素
line = ','.join(item)
# 将转换后的字符串写入文件
file2.write(line)
# 写入换行符,以分隔每一行数据
file2.write('\n')
def my_read_table():
# 定义一个空列表,用于存储读取的数据
data = []
# 打开文件 'wmcshopping.csv' 以读模式 ('r') 打开,并指定编码为 'utf-8'
with open('wmcshopping.csv', 'r', encoding='utf-8') as file2:
# 使用 readlines() 方法读取文件的每一行,并返回一个列表,其中每个元素为文件的一行
lst = file2.readlines()
# 遍历每一行数据
for item in lst:
# 使用切片操作移除每行末尾的换行符,并使用 split() 方法将字符串转换为列表,分隔符为逗号
new_lst = item[:len(item)-1:].split(',')
# 将转换后的列表添加到 data 列表中
data.append(new_lst)
# 打印存储的二维数据
print(data)
if __name__ == '__main__':
# 调用 my_write() 函数
# my_write()
# 调用 my_read() 函数
# my_read()
# 调用 my_write_table() 函数
# my_write_table()
# 调用 my_read_table() 函数
my_read_table()
3.4 例11.7:高维数据的存储
import json
# 准备高维数据
lst=[
{'name':'Leo','age':21,'score':3.89},
{'name':'Hazel','age':21,'score':3.93},
{'name':'Karen','age':21,'score':3.87}
]
s=json.dumps(lst,ensure_ascii=False,indent=4)
# ensure_ascii用以正常显示字符,indent为缩进,增强JSON字符串可读性
print(type(s)) # 编码:list-->str
print(s)
# 解码:str-->list
lst2=json.loads(s)
print(type(lst2))
print(lst2)
# 编码到文件中
with open('student.txt','w') as file1:
json.dump(lst,file1,ensure_ascii=False,indent=4)
# 解码到程序
with open('student.txt','r') as file1:
lst3=json.load(file1)
print(type(lst3),lst3)
4 目录与文件的相关操作
4.1 OS模块
OS模块是Python内置的与操作系统文件相关的模块,该模块中语句的执行结果通常与操作系统相关,即运行环境的差异(如Windows和MacOS)可能导致结果存在差异。
4.1.1 常用函数
函数名称 | 说明 |
---|---|
getcwd() | 获取当前工作路径 |
listdir(path) | 获取path路径下的文件和目录信息 如无指定path,则获取当前路径下的文件和目录信息 |
mkdir(path) | 在指定路径下创建目录(文件夹) |
makedirs(path) | 创建多级目录 |
rmdir(path) | 删除path下的空目录 |
removedirs(path) | 删除多级目录 |
chdir(path) | 把path设置为当前目录 |
walk(path) | 遍历目录树,结果为元组,包含所有路径名、所有目录列表和文件列表 |
remove(path) | 删除path指定的文件 |
rename(a,b) | 将a重命名为b |
stat(path) | 获取path指定的文件信息 |
startfule(path) | 启动path指定的文件 |
4.1.2 例11.8:OS模块的使用:创建目录/删除目录/改变工作路径/遍历目录树
import os
print('current path:',os.getcwd())
lst=os.listdir()
print('all directories and files in current path:',lst)
print('all directories and files in specific path:',os.listdir('D:/'))
# 创建目录
os.mkdir('folder1')
# 若当前路径下已存在同名目录,则报错(FileExistError: [WinError 183])
# 创建多级目录
os.makedirs('./f1/f2/f3')
# 删除空目录
os.rmdir('folder1')
# 同样效果:os.rmdir('./folder1')
# 若重复执行或文件夹不存在,会报错FileNotFoundError: [WinError 2]
os.removedirs('./f1/f2/f3') # 删除多级目录
# 改变当前路径
print('current path:',os.getcwd())
os.chdir('D:/')
print('current path (changed):',os.getcwd())
# python文件路径没变,程序运行路径发生改变
# walk()遍历目录树:递归操作
for dirs,dirlst,filelst in os.walk('D:/'):
print(dirs)
print(dirlst)
print(filelst)
print('-'*20)
4.1.3 例11.9:OS模块的高级操作:删除文件/重命名文件/查看文件信息/启动文件
import os
# 删除文件
os.remove('./a.txt')
# 若重复执行或文件不存在,会报错FileNotFoundError: [WinError 2]
# 重命名文件
os.rename('./aa.txt','./new_aa.txt')
# 若重复执行或文件不存在,会报错FileNotFoundError: [WinError 2]
# 查看文件信息
import time # 转换时间信息
def date_form(longtime):
s=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(longtime))
return s
info=os.stat('./new_aa.txt')
print(type(info),info)
print('last time to visit this file:',date_form(info.st_atime))
print('last time to modify this file:',date_form(info.st_mtime))
print('creation time in Win system:',date_form(info.st_ctime))
print('storage of this file:',date_form(info.st_size),'B')
# 启动路径下的文件
os.startfile('calc.exe') # 打开计算器(效果视同Win+R)
os.startfile(r"C:\Users\23608\AppData\Local\Programs\Python\Python311\python.exe") # 前写r避免Python识别路径中的右斜杠为转义字符
4.2 os.path模块
os.path模块是OS模块的子模块,也提供了一些目录或文件的操作函数。
4.2.1 常用函数
函数名称 | 说明 |
---|---|
abspath(path) | 获取目录或文件的绝对路径 |
exists(path) | 判断目录或文件在磁盘上是否存在,结果为布尔类型 若存在结果为True,反之为False |
join(path,name) | 将目录与目录名或文件名进行拼接,相当于字符串的“+”操作 |
splitext() | 分别获取文件名和后缀名 |
basename(path) | 从path中提取文件名 |
dirname(path) | 从path中提取路径(不包含文件名) |
isdir(path) | 判断path是否为有效路径 |
isfile(path) | 判断file是否为有效文件 |
4.2.2 例11.10:os.path模块的使用
import os.path
# 获取绝对路径
print('absolute path:', os.path.abspath('./b.txt'))
# 解释:os.path.abspath() 返回指定路径的绝对路径。
# 判断文件是否存在
print('if "b.txt" exists:', os.path.exists('./b.txt'))
print('if "new_b.txt" exists:', os.path.exists('./new_b.txt'))
# 解释:os.path.exists() 检查指定路径是否存在。
# 判断目录是否存在
print('if "folder1" exists:', os.path.exists('./folder1'))
# 解释:os.path.exists() 也可以用于检查目录是否存在。
# 拼接路径
print('complete path:', os.path.join('D:/', 'b.txt'))
# 解释:os.path.join() 将多个路径组合成一个路径。
# 分割文件名和后缀名
print('split name and suffix:', os.path.splitext('b.txt'))
# 解释:os.path.splitext() 将文件名和扩展名分开,返回一个元组。
# 提取文件名/路径
print('extract file name:', os.path.basename('D:/b.txt'))
print('extract file directory:', os.path.dirname('D:/b.txt'))
# 解释:os.path.basename() 提取路径中的文件名,
# os.path.dirname() 提取路径中的目录名。
# 验证路径/文件有效性
print('validity of a directory:', os.path.isdir('D:/'))
print('validity of a file:', os.path.isfile('D:/b.txt'))
# 解释:os.path.isdir() 检查路径是否是一个目录,
# os.path.isfile() 检查路径是否是一个文件。