admin管理员组文章数量:1558101
Python系列文章目录
第一章 Python 入门
第二章 Python基本概念
第三章 序列
第四章 控制语句
第五章 函数
第六章 面向对象基础
第七章 面向对象深入
第八章 异常机制
第九章 文件操作
文件操作
- Python系列文章目录
- 前言
- 一、什么是文件操作
- 1. 文件分类
- 2. 常用编码
- ASCII
- GBK
- Unicode
- UTF-8
- 二、文件操作
- 1. 创建文件对象
- 2. 文件的写入
- 基本文件的写入操作
- 中文乱码
- 代码编写时
- 控制台输出时
- write()/writelines()写入数据
- close()关闭文件流
- with语句(上下文管理器)
- 3. 文件的读取
- 二进制文件的读取和写入
- 4. 文件对象的常用属性和方法
- 文件任意位置操作
- 三、文件操作拓展模块
- 1. pickle序列化模块
- 2. csv文件的操作
- csv文件读取
- csv文件写入
- 3. os和os.path模块
- os模块-调用操作系统命令
- os模块-文件和目录操作
- os.path模块
- walk()递归遍历所有文件和目录
- 递归遍历目录下所有文件
- 4. shutil模块(拷贝和压缩)
前言
在本章节, 主要介绍了文件操作相关的API方法使用
首先我们将会学习什么是文件操作, 以及文件分类还有在IO操作时会用到的常用编码介绍
然后我们学习了文件操作的流程, 创建->写入->关闭
在然后我们学习了文件的拓展, 序列化模块pickle, 文件操作模块csv, 系统操作调用模块os和os.path以及文件拷贝压缩模块shutil
一、什么是文件操作
一个完整的程序一般都包括数据的存储和读取;我们在前面写的程序数据都没有进行实际的存储,因此python解释器执行完数据就消失了
实际开发中,我们经常需要从外部存储介质(硬盘、光盘、U盘等)读取数据,或者将程序产生的数据存储到文件中,实现“持久化”保存
1. 文件分类
按文件中数据组织形式,我们把文件分为文本文件和二进制文件两大类:
-
文本文件
文本文件存储的是普通“字符”文本,python默认为 unicode 字符集,可以使用记事本程序打开 -
二进制文件
二进制文件把数据内容用“字节”进行存储,无法用记事本打开, 必须使用专用的软件解码.
常见的有:MP4视频文件、MP3音频文件、JPG图片、doc文档等等
2. 常用编码
在操作文本文件时,经常会操作中文,这时候就经常会碰到乱码问题.
为了解决中文乱码问题,需要学习下各个编码之前的问题.
常用编码之间的关系如下:
ASCII
全称为 American Standard Code for Information Interchange ,美国信息交换标准代码,
这是世界上最早最通用的单字节编码系统,主要用来显示现代英语及其他西欧语言
注意事项:
- ASCII 码用7位表示,只能表示128个字符. 只定义了
2^7=128
个字符,用7bit即可完全编码,
而一字节8bit的容量是256,所以一字节 ASCII 的编码最高位总是0 - ASCll 码对应码表如下: ASCll 码表
GBK
GBK即汉字内码扩展规范,英文全称Chinese Internal Code Specification.
GBK编码标准兼容GB2312,共收录汉字21003个、符号883个,并提供1894个造字码位,简、繁体字融于一库。
GBK采用双字节表示,总体编码范围为8140-FEFE,首字节在81-FE 之间,尾字节在40-FE 之间
Unicode
Unicode 编码设计成了固定两个字节,所有的字符都用16位
2^16=65536
表示,包括之前只占8位的英文字符等,所以会造成空间的浪费
Unicode 完全重新设计,不兼容 iso8859-1 ,也不兼容任何其他编码
UTF-8
对于英文字母, unicode 也需要两个字节来表示, 所以 unicode 不便于传输和存储.
因此而产生了 UTF编码 , UTF-8 全称是( 8-bit UnicodeTransformation Format )
注意事项
- UTF 编码兼容 iso8859-1 编码,同时也可以用来表示所有语言的字符
- UTF 编码是不定长编码,每一个字符的长度从1-4个字节不等.
英文字母都是用一个字节表示,而汉字使用三个字节 - 一般项目都会使用 UTF-8
我们之所以倾向于使用UTF-8 , 是因为其不定长编码可以在节省内存的同时能够完全兼容中文
二、文件操作
1. 创建文件对象
open() 函数用于创建文件对象,基本语法格式如下: open(文件名[,打开方式])
注意:
-
如果只是文件名,代表在当前目录下的文件. 文件名可以录入全路径,比如:
D:\a\b.txt
可以使用原始字符串r“d:\b.txt”
减少\
的输入, 因此以上代码可改写成f = open(r"d:\b.txt","w")
-
作为入参的打开方式如下(经常会用!!!)
-
文本文件对象和二进制文件对象的创建
如果是二进制模式 b ,则创建的是二进制文件对象,处理的基本单元是“字节”
如果没有增加模式 b ,则默认创建的是文本文件对象,处理的基本单元是“字符”
2. 文件的写入
文本文件的写入一般就是三个步骤:
- 创建文件对象
- 写入数据
- 关闭文件对象
基本文件的写入操作
实操代码
# 1.使用open()方式
f = open(r"d:\a.txt", "a")
s = "TimePause\n时间静止\n"
f.write(s)
f.close()
结果展示
中文乱码
代码编写时
windows 操作系统默认的编码是 GBK , Linux 操作系统默认的编码是 UTF- 8 .
当我们用 open() 时,调用的是操作系统相关api来打开的文件,并且默认的编码是 GBK
但是由于我们通常习惯将所有代码编码都设置成 UTF- 8 ., 因此在打开时会出现乱码问题, 如下图所示
解决方案:
按照上图提示, 将文本编码设置成 GBK格式读取即可
注意:
我们还可以通过指定编码来解决中文乱码问题. 因为我们将pycharm
文本读写编码都设置成 utf-8,
因此只要我们在文件写入的时候规定编码为 utf-8(默认gbk), 那么我们在读取时就不会出现乱码. 如下代码
实操代码
# 【示例】通过指定文件编码解决中文乱码问题
f = open(r"d:\bb.txt", "w", encoding="utf-8")
f.write("一个有温情的小站\n时间静止不是简史")
f.close()
控制台输出时
问题描述
我们一般习惯把pycharm所有字符编码设置成utf-8时. 在我们进行网络请求时, 有时候会返回乱码问题, 如下图
问题分析
因为我们在 pycharm 设置所有字符编码均为 UTF-8, 但是通过网络请求得到GBK格式的文本, 然后我们仍以 UTF-8 编码去解码就会出现乱码
解决方案
可以将项目编码设置成GBK格式即可; 也可以通过文本操作代码对得到的数据进行GBK格式读取
亦或者在写入时, 直接将编码声明为UTF-8
write()/writelines()写入数据
write(a)
:把字符串 a 写入到文件中writelines(b)
:把字符串列表写入文件中,不添加换行符
实操代码
# 【操作】添加字符串列表数据到文件中
f = open(r"d:\bb.txt", 'w', encoding="utf-8")
s = ["什么鬼\n"] * 3 # 通过 \n实现手动换行
f.writelines(s)
f.close()
close()关闭文件流
由于文件底层是由操作系统控制,所以我们打开的文件对象必须显式调用 close() 方法关闭文件对象.
当调用 close() 方法时,首先会把缓冲区数据写入文件(也可以直接调用 flush() 方法),再关闭文件,释放文件对象
注意:
close()
一般结合异常机制的 finally 一起使用- 也可以通过 with 关键字实现无论何种情况都能关闭打开的文件对象(推荐)
实操代码
# 【操作】结合异常机制的 finally ,确保关闭文件对象
# "a" 设置打开方式为追加模式
try:
f = open(r"d:\c.txt", "a")
s = "来自深渊"
f.write(s)
except BaseException as e:
print(e)
finally:
f.close()
with语句(上下文管理器)
with关键字 (上下文管理器)可以自动管理上下文资源,不论什么原因跳出 with块 ,都能确保文件正确的关闭,
并且可以在代码块执行完毕后自动还原进入该代码块时的现场
实操代码
# 【操作】使用 with 管理文件写入操作
s = ["齐格飞"] * 3
with open(r"d:\cc.txt", "w") as f:
f.writelines(s)
3. 文件的读取
文件读取的步骤:
- 打开文本文件对象
- 写入数据
文件的读取一般使用如下三个方法:
-
read([size])
: 从文件中读取 size 个字符,并作为结果返回
如果没有 size 参数,则读取整个文件. 读取到文件末尾,会返回空字符串 -
readline()
: 读取一行内容作为结果返回
读取到文件末尾,会返回空字符串 -
readlines()
: 文本文件中,每一行作为一个字符串存入列表中,返回该列表
代码格式
with open(r"d:\a.txt", "r"[, encoding="utf-8"]) as f:
f.read(4)
注意:
- 在读取文件时, 需要注意读写时字符编码的一致性, 如果写的时候没有指定编码(默认GBK), 则在读取的时候也不需要指定编码
- 但如果读的时候未指定编码, 写的时候指定, 则会报错.
例如: 写的时候指定encoding="utf-8"
,
则控制台报UnicodeDecodeError: 'utf-8' codec can't decode byte 0xbc in position 13: invalid start byte
实操代码
# 【操作】 读取一个文件前4个字符
import pickle
with open(r"d:\a.txt", "r") as f:
print(f.read(4))
# 【操作】文件较小,一次将文件内容读入到程序中
with open(r"d:\aa.txt", "r") as f:
print(f.read())
# 【操作】按行读取一个文件
with open(r"d:\b.txt") as f:
while True:
lines = f.readline()
if not lines: # 在python 中 if not 会将后面对象隐式转成True或者False进行判断, 因此遇到空字符串也返回False
break
else:
print(lines, end="")
print()
# 【操作】使用迭代器(每次返回一行)读取文本文件
# 写和读的编码要对应
with open(r"d:\bb.txt", "r", encoding="utf-8") as f:
for a in f:
print(a, end="")
# 【操作】为文本文件每一行的末尾增加行号
with open(r"d:\c.txt", "r") as f:
lines = f.readlines()
lines2 = [line.rstrip() + " # " + str(index) + "\n" for index, line in zip(range(1, len(lines) + 1), lines)]
with open(r"d:\c.txt", "w") as ff:
ff.writelines(lines2)
二进制文件的读取和写入
二进制文件的处理流程和文本文件流程一致。首先还是要创建文件对象,
创建好二进制文件对象后,仍然可以使用 write() 、 read() 实现文件的读写操作
在创建文件对象时, 首先需要指定二进制模式,然后才能创建出二进制文件对象. 例如
f = open(r"d:\a.txt", 'wb')
可写的、重写模式的二进制文件对象f = open(r"d:\a.txt", 'ab')
可写的、追加模式的二进制文件对象f = open(r"d:\a.txt", 'rb')
可读的二进制文件对象
实操代码
# 二进制文件的读取和写入(此操作相当于复制)
# f = open(r"d:\a.txt", 'wb') #可写的、重写模式的二进制文件对象
# f = open(r"d:\a.txt", 'ab') #可写的、追加模式的二进制文件对象
# f = open(r"d:\a.txt", 'rb') #可读的二进制文件对象
with open(r"d:\aaa.png", "rb") as scrFile, open(r"d:\bbb.png", "wb") as destFile:
for l in scrFile:
destFile.write(l)
4. 文件对象的常用属性和方法
文件对象的属性
文件对象的打开模式
文件对象的常用方法
文件任意位置操作
利用 seek() 可以将读取文件的指针移动到指定字节位置上
一个中文字符站两个字节, 而英文只占一个字节
实操代码
print("=================文件任意位置操作======================")
# 【示例】 seek() 移动文件指针示例
with open(r"d:\cc.txt", "r") as f:
print("文件名是{0}".format(f.name)) # 文件名是d:\cc.txt
print(f.tell()) # 0
print("读取文件的内容", str(f.readline())) # 读取文件的内容 齐格飞齐格飞齐格飞
print(f.tell()) # 18
f.seek(4, 0) # 中文占2个字节, 因此在seek时需要是2的倍数
print("文件读取的内容", str(f.readline())) # 文件读取的内容 飞齐格飞齐格飞
print(f.tell()) # 18
三、文件操作拓展模块
1. pickle序列化模块
序列化指的是:将对象转化成“串行化”数据形式,存储到硬盘或通过网络传输到其他地方.
反序列化是指相反的过程,将读取到的“串行化数据”转化成对象
可以使用pickle模块中的函数,实现序列化和反序列操作
序列化我们使用:
pickle.dump(obj, file)
obj 就是要被序列化的对象, file 指的是存储的文件pickle.load(file)
从 file 读取数据,反序列化成对象
实操代码
import pickle
print("=================使用pickle序列化=======================")
# 【操作】将对象序列化到文件中
with open("student.info", "wb") as f:
name = "时间静止"
age = 18
score = [90, 80, 70]
resume = {"name": name, "age": age, "score": score}
pickle.dump(resume, f)
# 【操作】将获得的数据反序列化成对象
with open("student.info", "rb") as f:
resume = pickle.load(f)
print(resume)
2. csv文件的操作
csv是逗号分隔符文本格式,常用于数据交换、Excel文件和数据库数据的导入和导出
与Excel文件不同,CSV文件中:
- 值没有类型,所有值都是字符串
- 不能指定字体颜色等样式
- 不能指定单元格的宽高,不能合并单元格
- 没有多个工作表
- 不能嵌入图像图表
Python标准库的模块csv提供了读取和写入csv格式文件的对象
我们在excel中建立一个简单的表格并且另存为 csv(逗号分隔) ,我们打开查看这个csv文件内容
csv文件读取
实操代码
import csv
with open(r"d:\workBook.csv") as a:
o_csv = csv.reader(a) # #创建csv对象,它是一个包含所有数据的列表,每一行为一个元素
headers = next(o_csv) # #获得列表对象,包含标题行的信息
print(headers)
for row in o_csv: # 循环打印各行内容
print(row)
结果展示
csv文件写入
实操代码
# 【操作】 csv.writer 对象写一个csv文件
headers = ['姓名', '年龄', '工作', '住址']
rows = [('JOJO', '18', '按摩师', '英国'), ('迪奥', '19', '老板', '埃及'), ('乔鲁诺乔巴纳', '20', '混混', '意呆利')]
with open(r"d:\workBook3.csv", "w") as b:
b_scv = csv.writer(b) # 创建csv对象
b_scv.writerow(headers) # 写入一行(标题)
b_scv.writerows(rows) # 写入多行(数据)
结果展示
3. os和os.path模块
os模块 可以帮助我们直接对操作系统进行操作.
我们可以直接调用操作系统的可执行文件、命令,直接操作文件、目录等等
os模块 是做系统运维非常重要的基础
os模块-调用操作系统命令
实操代码
# 【示例】 os.system 调用windows系统的记事本程序
os.system("notepad.exe")
# 【示例】 os.system 调用windows系统中ping命令
# 如果出现乱码, 请看 文件操作->文件的写入->中文乱码->控制台输出时 进行配置
os.system("ping www.baidu")
# 【示例】运行安装好的微信
os.startfile(r"C:\Program Files (x86)\Tencent\WeChat\WeChat.exe")
os模块-文件和目录操作
可以通过前面讲的文件对象实现对于文件内容的读写操作.
如果还需要对文件和目录做其他操作,可以使用 os 和 os.path 模块.
- os 模块下常用操作文件的方法
- os 模块下关于目录操作的相关方法
实操代码
import os
# 【示例】 os 模块:创建、删除目录、获取文件信息等
print("系统名称:", os.name) # windows-->nt linux-->posix
print("当前操作系统所使用的路径分隔符:", os.sep) # windows-->\ linux-->/
print("行间隔符:", repr(os.linesep)) # windows-->\r\n linux-->\n
print("当前目录:", os.curdir)
a = "3"
print(a)
# 返回对象的规范字符串表示
print(repr(a))
# 获取文件和文件夹的相关信息
print(os.stat("MyPy08-FileRead.py"))
# 工作目录的操作
print(os.getcwd()) # 获取当前工作目录
os.chdir("D:") # 切换当前工作目录
os.mkdir("学习资料大全") # 创建目录
os.rmdir("学习资料大全") # 删除目录
# os.makedirs("人种/黄种人/中国人") # 创建多级目录, 调用成功一次之后, 再次调用会报错
# os.rename("人种", "亚洲人") # 此方法也只能调用一次
print(os.listdir("亚洲人")) # 当前目录下的子目录
注意事项
在调用 os.rename()
时, 如果出现报错 PermissionError: [WinError 5] 拒绝访问
,
则需要你在需要重命名的文件夹上面配置用户的权限. 修改之后便可进行重命名. 如下图所示
os.path模块
os.path 模块提供了目录相关(路径判断、路径切分、路径连接、文件夹遍历)的操作
实操代码
# 【示例】测试 os.path 中常用方法
print("是否是绝对路径:", os.path.isabs("d:/a.txt"))
print("是否是目录: ", os.path.isdir(r"d:\a.txt"))
print("文件是否存在: ", os.path.exists("a.txt"))
print("文件大小: ", os.path.getsize("a.txt"))
print("输出绝对路径:", os.path.abspath("a.txt"))
print("输出所在目录:", os.path.dirname("d:/a.txt"))
# 获得创建时间、访问时间、最后修改时间
print("输出创建时间:", os.path.getctime("a.txt"))
print("输出最后访问时间:", os.path.getatime("a.txt"))
print("输出最后修改时间", os.path.getmtime("a.txt"))
# 对路径进行分割、连接操作
path = os.path.abspath("a.txt") # 返回绝对路径
print("返回元组:目录、文件:", os.path.split(path))
print("返回元组:路径、扩展名", os.path.splitext(path))
print("返回路径:aa\bb\cc", os.path.join("aa", "bb", "cc"))
列出指定目录下所有的 .py 文件,并输出文件名
# 列出指定目录下所有的 .py 文件,并输出文件名
import os
path = os.getcwd()
file_list = os.listdir(path)
for filename in file_list:
pos = filename.rfind(".")
if filename[pos + 1:] == "py":
print(filename, end="\t")
print()
walk()递归遍历所有文件和目录
os.walk() 方法是一个简单易用的文件、目录遍历器,可以帮助我们高效的处理文件、目录方面的事情
格式如下: os.walk(top[, topdown=True[, onerror=None[, followlinks=False]]])
- top :是要遍历的目录。 topdown :可选, True ,先遍历 top 目录再遍历子目录
- 返回三元组( root 、 dirs 、 files ):
root :当前正在遍历的文件夹本身
dirs :一个列表,该文件夹中所有的目录的名字
files :一个列表,该文件夹中所有的文件的名字
实操代码
# 【示例】使用 walk() 递归遍历所有文件和目录
path = os.getcwd()[:os.getcwd().rfind("\\")] # 获取上级路径, 作用是能够输出更多的文件
file_list = os.walk(path, topdown=False)
for root, dirs, files in file_list:
for name in files:
print(os.path.join(root, name))
for name in dirs:
print(os.path.join(root, name)) # 用于拼接目录
输出结果
递归遍历目录下所有文件
实操代码
# 【示例】使用递归算法遍历目录下所有文件
def my_print_file(path, level):
child_files = os.listdir(path)
for file in child_files:
file_path = os.path.join(path, file)
print("\t" * level + file_path[file_path.rfind(os.sep)+1:])
if os.path.isdir(file_path):
my_print_file(file_path, level + 1)
my_print_file(path, 0)
4. shutil模块(拷贝和压缩)
shutil 模块是python标准库中提供的,主要用来做文件和文件夹的拷贝、移动、删除等;
还可以做文件和文件夹的压缩、解压缩操作. os 模块提供了对目录或文件的一般操作.
shutil 模块作为补充,提供了移动、复制、压缩、解压等操作,这些 os 模块都没有提供
实操代码-拷贝
import shutil
# 【示例】实现文件的拷贝
os.chdir("D:") # 切换当前工作目录
shutil.copyfile("a.txt", "a_copy.txt")
# 【示例】实现递归的拷贝文件夹内容(使用 shutil 模块)
shutil.copytree("亚洲人/黄种人", "人种", ignore=shutil.ignore_patterns("*.html", "*htm")) # "音乐"文件夹不存在才能用
实操代码-压缩与解压
# 【示例】实现将文件夹所有内容压缩(使用 shutil 模块)
# 将"亚洲人/黄种人"文件夹下所有内容压缩到"生物资料"文件夹下生成race.zip
shutil.make_archive("生物资料/race", "zip", "亚洲人/黄种人")
# 压缩:将指定的多个文件压缩到一个zip文件
z = zipfile.ZipFile("a.zip", "w")
z.write("a.txt")
z.write("b.txt")
z.close()
# 【示例】实现将压缩包解压缩到指定文件夹(使用 shutil 模块)
z2 = zipfile.ZipFile("a.zip", "r")
z2.extractall("d:/生物资料")
z2.close()
版权声明:本文标题:Python升级之路( Lv9 ) 文件操作 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/xitong/1727332953a1108766.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论