文件
1.文件操作
- 简介:
一个完整的程序一般都包括数据的存储和读取;开发中,我们经常需要从外部存储介质(硬盘、光盘、U盘等)读取数据,或者将程序产生的数据存储到文件中,实现“持久化”保存。
2. 文本文件和二进制文件
- 简介:
按文件中数据组织形式,我们把文件分为文本文件和二进制文件两大类。 - 文本文件:
文本文件存储的是普通“字符”文本,python默认为unicode
字符集(两个字节表示一个字符,最多可以表示:65536个),可以使用记事本程序打开。 - 二进制文件:
二进制文件把数据内容用“字节”进行存储,无法用记事本打开。必须使用专用的软件解码。常见的有:MP4视频文件、MP3音频文件、JPG图片、doc文档等等。
- 文件操作相关模块概述:
Python标准库中,如下是文件操作相关的模块:名称 说明 io
模块文件流的输入和输出操作 input output os
模块基本操作系统功能,包括文件操作 glob
模块查找符合特定规则的文件路径名 fnmatch
模块使用模式来匹配文件路径名 fileinput
模块处理多个输入文件 filecmp
模块用于文件的比较 csv
模块用于csv文件处理 pickle
和cPickle
用于序列化和反序列化 xml
包用于XML数据处理 bz2
、gzip
、zipfile
、zlib
、tarfile
用于处理压缩和解压缩文件(分别对应不同的算法)
3.创建文件对象open()
-
open() 函数用于创建文件对象,
-
基本语法格式如下:
open(文件名[,打开方式])
-
如果只是文件名,代表在当前目录下的文件。文件名可以录入全路径,比如:
D:\a\b.txt
-
为了减少
\
的输入,可以使用原始字符串:r“d:\b.txt”
示例如下:f = open(r"d:\b.txt","w")
-
打开方式有如下几种:
模式 描述 'r'
以只读模式打开文件,如果文件不存在则会抛出 FileNotFoundErro
错误'w'
写入文件,如果不存在则创建,如果存在则会将原有内容覆盖 'x'
写入文件,如果文件不存在则创建,如果文件存在,则抛出 FileExistsError
错误'a'
写入文件,如果文件存在则以追加的方式写入文件,如果不存在则会创建文件并写入 'b'
二进制模式,需要配合读写来使用,不可单独使用 't'
文本模式 '+'
不可单独使用,需配合其他一起使用 'r+'
以读写方式打开文件,文件存在则会覆盖内容,不存在则会抛出 FileNotFoundError
'a+'
以追加的方式打开文件,不会覆盖原有内容,调用 readable()
返回True
,readline()
返回空readlines()
返回空列表'w+'
文件不存在则新建,存在则将原有内容清空 -
注意:
文本文件对象和二进制文件对象的创建:- 如果没有增加模式
b
,则默认创建的是文本文件对象,处理的基本单元是“字符”。 - 如果是二进制模式
b
,则创建的是二进制文件对象,处理的基本单元是“字节”。
- 如果没有增加模式
4.文本文件的写入
- 基本的文件写入操作
文本文件的写入一般就是三个步骤:- 创建文件对象
- 写入数据
- 关闭文件对象
- 代码示例:
- 初始操作
f = open(r"a.txt","a") s = "hello\nworld\n" f.write(s) f.close()
with
上下文管理器(简单提一下)
with open(r"a.txt","a") as f: s = "hello\nworld\n" f.write(s)
5.常用编码介绍
- 简介:
在操作文本文件时,经常会操作中文,这时候就经常会碰到乱码问题。为了让大家有能力解决中文乱码问题,这里简单介绍一下各种编码之间的关系。
常用编码之间的关系如下:
ASCII
全称为 American Standard Code for Information Interchange ,美国信息交换标准代码,这是世界上最早最通用的单字节编码系统,主要用来显示现代英语及其他西欧语言。ASCII
码用7位表示,只能表示128个字符。只定义了27=128个字符,用7bit即可完全编码,而一字节8bit的容量是256,所以一字节ASCII
的编码最高位总是0。0~31表示控制字符如回车、退格、删除等;32~126表示打印字符即可以通过键盘输入并且能显示出来的字符; 其中48~57为0到9十个阿拉伯数字,65~90为26个大写英文字母,97~122号为26个小写英文字母,其余为一些标点符号、运算符号等,具体可以参考ASCII 标准表。ISO8859-1
ISO-8859-1
又称Latin-1
,是一个8位单字节字符集,它把ASCII
的最高位也利用起来,并兼容了ASCII
,新增的空间是128,但它并没有完全用完。在ASCII
编码之上又增加了西欧语言、希腊语、泰语、阿拉伯语、希伯来语对应的文字符号,它是向下兼容ASCII
编码GB2312
,GBK
,GB18030
GB2312
GB2312
全称为信息交换用汉字编码字符集,是中国于1980年发布,主要用于计算机系统中的汉字处理。GB2312
主要收录了6763个汉字、682个符号。GB2312
覆盖了汉字的大部分使用率,但不能处理像古汉语等特殊的罕用字,所以后来出现了像GBK
、GB18030
这种编码。GB2312
完全兼容ISO8859-1
GBK
全称为 Chinese Internal Code Specification ,即汉字内码扩展规范,于1995年制定。它主要是扩展了 GB2312 ,在它的基础上又加了更多的汉字,
它一共收录了21003个汉字GB18030
现在最新的内码字集于2000年发布,并于2001年强制执行,包含了中国大部分少数民族的语言字符,收录汉字数超过70000余个。它主要采用单字节、双字节、四字节对字符编码,它是向下兼容GB2312
和GBK
的,虽然是我国的强制使用标准,但在实际生产中很少用到,用得最多的反而是GBK
和GB2312
Unicode
Unicode
编码设计成了固定两个字节,所有的字符都用16位(2^16=65536)表示,包括之前只占8位的英文字符等,所以会造成空间的浪费,UNICODE
在很长的一段时间内都没有得到推广应用。Unicode
完全重新设计,不兼容iso8859-1
,也不兼容任何其他编码。UTF-8
对于英文字母,unicode
也需要两个字节来表示。所以unicode
不便于
传输和存储。因此而产生了UTF
编码 ,UTF-8
全称是( 8-bit Unicode
Transformation Format )。UTF
编码兼容iso8859-1
编码,同时也可以用来表示所有语言的字符,不过,UTF
编码是不定长编码,每一个字符的长度从1-4个字节不等。其中,英文字母都是用一个字节表示,而汉字使用三个字节。
6.中文乱码问题
- 简介:
windows 操作系统默认的编码是GBK
, Linux 操作系统默认的编码是UTF-8
。当我们用open()
时,调用的是操作系统打开的文件,默认的编码是GBK
。 - 代码示例:
#测试写入中文 f = open(r"b.txt","w",encoding="utf-8") f.write("你好,世界") f.close()
7.write()/writelines()
写入数据
f.write(a)
:把字符串 a 写入到文件中f.writelines(b)
:把字符串列表 b 写入文件中,不添加换行符,需要自己在列表中加换行符\n
f.writable()
:检查文件是否可写,如果文件可写,则writable()
方法返回True
,否则返回False
。
如果使用 “a” 追加或使用 “w” 写入来打开文件,则该文件是可写的
8.close()
关闭文件流
- 简介:
由于文件底层是由操作系统控制,所以我们打开的文件对象必须显式调用close()
方法关闭文件对象。当调用close()
方法时,首先会把缓冲区数据写入文件(也可以直接调用flush()
方法),再关闭文件,释放文件对象。 finally()
关闭文件
为了确保打开的文件对象正常关闭,一般结合异常机制的 finally 或者
with 关键字实现无论何种情况都能关闭打开的文件对象。- 代码示例:
try: f = open(r"my01.txt","a") s = "hello world" f.write(s) except BaseException as e: print(e) finally: f.close()
9.with
上下文管理器
- 简介:
with
关键字(上下文管理器)可以自动管理上下文资源,不论什么原因跳出with
块 ,都能确保文件正确的关闭,并且可以在代码块执行完毕后自动还原进入该代码块时的现场。 - 代码示例:
with open(r"a.txt","a") as f: s = "hello\nworld\n" f.write(s)
10.文本文件的读取
read([size])
从文件中读取size
个字符,并作为结果返回。如果没有size
参数,则读取整个文件。读取到文件末尾,会返回空字符串。readline()
读取一行(一行一行读取)内容作为结果返回。读取到文件末尾,会返回空字符串readlines()
文本文件中,每一行作为一个字符串存入列表中,返回该列表- 代码示例读写:
- 为文件添加行符
with open(r"E:\my_python\测试\a.txt", "r+", encoding="utf-8") as f: fx = f.readlines() line_read = [line.rstrip() for line in fx] # print(liner) f.seek(0) # 读完文件将指针移动到初始位置 f.truncate() # 清空文件内容 line_write = list(map(lambda line1, line1_index: line1 + f" #{line1_index + 1}\n", [line1 for line1 in line_read], [line1_index for line1_index in range(len(line_read))])) # 添加行符的操作逻辑 f.writelines(line_write) # 原文件内容 hello world 你好 世界 # 运行结果 hello #1 world #2 你好 #3 世界 #4
11.二进制文件的读取和写入
- 简介:
二进制文件的处理流程和文本文件流程一致。首先还是要创建文件对象,不过,我们需要指定二进制模式,从而创建出二进制文件对象。例如: f = open(r"d:\a.txt", 'wb')
#可写的、重写模式的二进制文件对象f = open(r"d:\a.txt", 'ab')
#可写的、追加模式的二进制文件对象f = open(r"d:\a.txt", 'rb')
#可读的二进制文件对象
创建好二进制文件对象后,仍然可以使用write()
、read()
实现文件的读写操作。- 代码示例:
with open('logo1.png', 'rb')as srcFile,open("ddd.png","wb") as destFile: for line in srcFile: destFile.write(line)
12.文件对象的常用属性和方法
- 文件对象封装了文件相关的操作。在前面介绍了通过文件对象
对文件进行读写操作。如下详细列出文件对象的常用属性和方
法,并进行说明。 - 文件对象的属性
属性 说明 name
返回文件的名字 mode
返回文件的打开模式 closed
若文件被关闭, 则返回True - 文件对象的打开模式
见3.创建文件对象open()子目录5. 打开方式有如下几种 - 文件对象的常用方法
方法名 说明 read([size])
从文件中读取 size
个字节或字符的内容返回。若省略[size]
,则读取到文件末尾,即一次读取文件所有内容readline()
从文本文件中读取一行内容 readlines()
把文本文件中每一行都作为独立的字符串对象,并将这些对象放入列表返回 write(str)
将字符串 str
内容写入文件writelines(s)
将字符串列表 s
写入文件文件,不添加换行符seek(offset[,whence])
把文件指针移动到新的位置, offset
表示相对于whence
的多少个字节的偏移量;offset
:off
为正往结束方向移动,为负往开始方向移动whence
不同的值代表不同含义:0
: 从文件头开始计算(默认值)1
:从当前位置开始计算2
:从文件尾开始计算tell()
返回文件指针的当前位置 truncate([size])
不论指针在什么位置,只留下指针前 size
个字节的内容,其余全部删除;如果没有传入size
,则当指针当前位置到文件末尾内容全部删除flush()
把缓冲区的内容写入文件,但不关闭文件 close()
把缓冲区内容写入文件,同时关闭文件,释放文件对象相关资源
13.文件任意位置操作
- 代码示例:
#e.txt的内容是:abcefghljklmn with open("e.txt","r",encoding="utf-8") as f: print("文件名是:{0}".format(f.name)) #文 件名是:e.txt print(f.tell()) #0 print("读取的内容: {0}".format(str(f.readline()))) #读取的内容: abcdefghijklmn print(f.tell()) #14 f.seek(3,0) print("读取的内容: {0}".format(str(f.readline()))) #读取的内容: defghijklmn
14.使用pickle
序列化
- 序列化指的是:将对象转化成“串行化”数据形式,存储到硬盘或通过网络传输到其他地方。反序列化是指相反的过程,将读取到的“串行化数据”转化成对象。
- 我们可以使用
pickle
模块中的函数,实现序列化和反序列操作。Python中,一切皆对象,对象本质上就是一个“存储数据的内存块”。有时候,我们需要将“内存块的数据”保存到硬盘上,或者通过网络传输到其他的计算机上。这时候,就需要“对象的序列化和反序列化”。 对象的序列化机制广泛的应用在分布式、并行系统上。 - 序列化我们使用:
pickle.dump(obj, file)
obj
: 就是要被序列化的对象file
: 指的是存储的文件
pickle.load(file)
从file
读取数据,反序列化成对象- 将对象序列化到文件中
import pickle with open(r"E:\my_python\测试\test.dat", "wb") as f: l = "hello world!" pickle.dump(l, f) # 运行结果 一串编码形式
- 将数据反序列化为对象
with open(r"E:\my_python\测试\test.dat", "rb") as f: ff = pickle.load(f) print(ff) # 运行结果 hello world
15.csv
文件的操作
- 简介:
csv
是逗号分隔符文本格式,常用于数据交换、Excel文件和数据库
数据的导入和导出。
与Excel文件不同,CSV文件中:- 值没有类型,所有值都是字符串
- 不能指定字体颜色等样式
- 不能指定单元格的宽高,不能合并单元格
- 没有多个工作表
- 不能嵌入图像图表
16.csv.reader
对象和csv
文件读取
csv.reader
对象于从csv
文件读取数据import csv with open(r"E:\my_python\测试\test1.csv") as f: f_csv = csv.reader(f) # 创建csv对象,它是一个包含所有数据的列表,每一行为一个元素 headers = next(f_csv) # 获得列表对象中第1个元素,每一行为一个元素,指针指在第一个元素 headers1 = next(f_csv) # 获得列表对象中第2个元素,每一行为一个元素,指针指在第二个元素 headers2 = next(f_csv) # 获得列表对象中第3个元素,每一行为一个元素,指针指在第三个元素 headers3 = next(f_csv) # 获得列表对象中第4个元素,每一行为一个元素,指针指在第四个元素 print(headers) print(headers1) print(headers2) print(headers3) for line in f_csv: # 循环打印指针后的列表中每一个元素 print(line) # 运行结果 ['编程语言', '薪资'] ['python', '12000'] ['java', '13000'] ['c', '11000']
17.csv.writer
对象和csv
文件写入
csv.writer
对象写一个csv
文件
我们发现import csv header = ["日期", "节日"] rows = [("10-1", "国庆节"), ("8-15", "中秋节"), ("9-9", "重阳节")] with open(r"E:\my_python\测试\test2.csv", "w") as f1: f1_csv = csv.writer(f1) f1_csv.writerow(header) f1_csv.writerows(rows) # 运行结果 日期,节日 10-1,国庆节 8-15,中秋节 9-9,重阳节
writerow
和writerows
写入csv
文件会导致新一行为空行,解决该问题的办法是:在文件处理open()
中添加选项newline=""
即可解决。header = ["日期", "节日"] rows = [("10-1", "国庆节"), ("8-15", "中秋节"), ("9-9", "重阳节")] with open(r"E:\my_python\测试\test2.csv", "w", newline="") as f1: f1_csv = csv.writer(f1) f1_csv.writerow(header) f1_csv.writerows(rows) # 运行结果 日期,节日 10-1,国庆节 8-15,中秋节 9-9,重阳节
18.os
和os.path
模块
- 简介:
os模块
可以帮助我们直接对操作系统进行操作。我们可以直接调用操
作系统的可执行文件、命令,直接操作文件、目录等等。
⚠️os
模块 是做系统运维非常重要的基础。 os
模块-调用操作系统命令
os.system
可以帮助我们直接调用系统的命令- 代码示例:
os.system
调用windows
系统的记事本程序
import os os.system("notepad.exe")
os.system
调用windows
系统中ping
命令
import os os.system("ping www.baidu.com")
os.startfile
:直接调用可执行文件
import os os.startfile(r"C:\Program Files (x86)\Tencent\WeChat\WeChat.exe")
os
模块-文件和目录操作-
简介:
我们可以通过前面讲的文件对象实现对于文件内容的读写操作。如果,还需要对文件和目录做其他操作,可以使用os
和os.path
模块。 -
os
模块下常用操作文件的方法方法名 描述 remove(path)
删除指定的文件 rename(src,dest)
重命名文件或目录 stat(path)
返回文件的所有属性 listdir(path)
返回 path
目录下的文件和目录列表 -
os
模块下关于目录操作的相关方法,汇总如下:方法名 描述 mkdir(path)
创建目录 makedirs(path1/path2/path3/...)
创建多级目录 rmdir(path)
删除目录 removedirs(path1/path2...)
删除多级目录 getcwd()
返回当前工作目录:current work dir chdir(path)
把path设为当前工作目录 walk()
遍历目录树 sep
当前操作系统所使用的路径分隔符 name
获取操作系统类型 - 代码示例:
os
模块:创建、删除目录、获取文件信息等
#测试os模块中,关于文件和目录的操作 import os #打印基本的信息 print(os.name) #windows-->nt linux-->posix print(os.sep) #windows-->\ linux-->/ print(repr(os.linesep)) #windows-->\r\n linux-->\n a = '3' print(a) print(repr(a)) #repr可以显示数据信息 #获取文件和文件夹的相关信息 print(os.stat("my01.py")) #关于工作目录的操作 print(os.getcwd()) #获得当前工作目录 os.chdir("d:") #当前的工作目录就变成了d:的根目录 ######创建目录、删除目录 #os.mkdir("书籍") #os.rmdir("书籍") ######创建多级目录 # os.makedirs("电影/港台/周星驰") # os.rename("电影","movie") dirs = os.listdir("movie") print(dirs)
- 代码示例:
-
os.path
模块提供了目录相关(路径判断、路径切分、路径连接、文件夹遍历)的操作方法 描述 isabs(path)
判断 path
是否绝对路径isdir(path)
判断 path
是否为目录isfile(path)
判断 path
是否为文件exists(path)
判断指定路径的文件是否存在 getsize(filename)
返回文件的大小 abspath(path)
返回绝对路径 dirname(p)
返回目录的路径 getatime(filename)
返回文件的最后访问时间 getmtime(filename)
返回文件的最后修改时间 walk(top,func,arg)
递归方式遍历目录 join(path,*paths)
连接多个path split(path)
对路径进行分割,以列表形式返回 splitext(path)
从路径中分割文件的扩展名 - 代码示例:测试
os.path
中常用方法
#测试os.path常用方法 import os #################获得目录、文件基本信息 ###################### print(os.path.isabs("d:/a.txt")) #是否绝对路径 print(os.path.isdir("d:/a.txt")) #是否目录 print(os.path.isfile("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)) #返回元组:目录、文件 ('C:\\Users\\Administrator\\PycharmProjects\ \mypro_io\\test_os', 'a.txt') print(os.path.splitext(path)) #返回元组:路径、扩展名 ('C:\\Users\\Administrator\\PycharmProjects\ \mypro_io\\test_os\\a', '.txt') print(os.path.join("aa","bb","cc")) #返回路径:aa/bb/cc
- 代码示例:测试
-
代码示例:列出指定目录下所有的
.py
文件,并输出文件名- 第一种方式:获取目录下的
.py
文件
import os import os.path path = os.getcwd() file_list = os.listdir(path) #列出子目录和子文件 # 方式1 for filename in file_list: pos = filename.rfind(".") # 找到“.”的index索引 if filename[pos+1:]=="py": # 判断后缀名为“py” print(filename,end="\t") print("##################") # 方式2 file_list2 = [filename for filename in os.listdir(path) if filename.endswith(".py")] for filename in file_list2: print(filename,end="\t")
- 第一种方式难以获取到目录下又嵌套子目录文件夹的文件,做如下改进:
import os path = r"E:\my_python\测试" def py_file(file_path): '''主要用来判断获取的文件是不是.py 如果是return True''' if os.path.isfile(file_path): if file_path.endswith(".py"): return True def listdir_fuc(path): '''递归函数用来递归文件夹目录的嵌套''' for file_path in os.listdir(path): if py_file(path+"\\"+file_path): # 对文件路径的处理 print(os.path.split(file_path)[1]) if os.path.isdir(path+"\\"+file_path): # 如果获取的是文件夹判断之后再次调用lisdir_fuc函数 listdir_fuc(path+"\\"+file_path) listdir_fuc(path)
- 第一种方式:获取目录下的
-
19.walk()
递归遍历所有文件和目录
os.walk()
方法是一个简单易用的文件、目录遍历器,可以帮助我们高效的处理文件、目录方面的事情。- 语法:
os.walk(top[, topdown=True[, onerror=None[, followlinks=False]]])
top
:是要遍历的目录。topdown
--可选,为True
,则优先遍历top
目录,否则优先遍历top
的子目录(默认为开启)。如果topdown
参数为True
,walk
会遍历top
文件夹,与top
文件夹中每一个子目录。onerror
– 可选,需要一个callable
对象,当walk
需要异常时,会调用。followlinks
– 可选,如果为True
,则会遍历目录下的快捷方式(linux
下是软连接symbolic link
)实际所指的目录(默认关闭),如果为False
,则优先遍历top
的子目录。
返回三元组(root
、dirs
、files
):root
:当前正在遍历的文件夹本身dirs
:一个列表,该文件夹中所有的目录的名字iles
:一个列表,该文件夹中所有的文件的名字
- 代码示例:
import os path = os.getcwd() print(path) list_files = os.walk(path, topdown=False) for root, dirs, files in list_files: for name in files: print(os.path.join(root, name)) # 合并当前目录和当前目录下文件的路径 for name in dirs: print(os.path.join(root, name)) # 合并当前目录和子目录路径
20.shutil
模块(拷贝和压缩)
- 简介:
shutil
模块是python标准库中提供的,主要用来做文件和文件夹的拷贝、移动、删除等;还可以做文件和文件夹的压缩、解压缩操作。os
模块提供了对目录或文件的一般操作。shutil
模块作为补充,提供了移动、复制、压缩、解压等操作,这些os
模块都没有提供。 - 代码示例:
- 实现文件的拷贝
import shutil #copy文件内容 shutil.copyfile("a.txt","a_copy.txt")
- 实现递归的拷贝文件夹内容(使用
shutil
模块)
将文件夹“电影/学习”下面的内容拷贝到文件夹“音乐”下。拷贝时忽略所有的 html 和 htm 文件。import shutil #"音乐"文件夹不存在才能用。 shutil.copytree("电影/学习","音乐",ignore=shutil.ignore_patterns("*.html","*.htm"))
- 实现将文件夹所有内容压缩(使用
shutil
模块)import shutil import zipfile #将"电影/学习"文件夹下所有内容压缩到"音乐2"文件夹下生成movie.zip #shutil.make_archive("音乐2/movie","zip","电影/学习") #压缩:将指定的多个文件压缩到一个zip文件 #z = zipfile.ZipFile("a.zip","w") #z.write("1.txt") #z.write("2.txt") #z.close()
- 实现将压缩包解压缩到指定文件夹(使用
shutil
模块)import shutil import zipfile #解压缩: z2 = zipfile.ZipFile("a.zip","r") z2.extractall("d:/") #设置解压的地址 z2.close()
- 实现文件的拷贝
21.递归遍历目录下所有文件(递归树实现)
import os
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(r"E:\my_python\测试", 0)