第5章 文件操作与管理 每个计算机程序都是用来解决特定问题的。较大规模的程序提供丰富的功能解决完整 的计算问题。无论程序规模如何,每个程序都有统一的运算模式:输入数据、处理数据和输 出数据。在程序运行时,数据保存在内存的变量里。内存中的数据在程序结束或关机后就 会消失。如果想要在下次开机运行程序时还使用同样的数据,就需要把数据存储在不易失 的存储介质中,如硬盘、光盘或U盘里。不易失存储介质上的数据保存在以存储路径命名 的文件中。通过读/写文件,程序就可以在运行时保存数据了。 1 文件与文件操作 5. 文件是常用的一种存储数据的载体,文件操作则是对数据进行管理的统称。程序经常 需要访问文件和目录,读取文件信息或写入信息到文件,在Python语言中对文件的读/写 是通过文件对象实现的。文件对象可以是实际的磁盘文件,也可以是其他存储或通信设备, 如内存缓冲区、网络、键盘和控制台等。 5.1 文件的定义 1. 在日常生活中,无论是Word还是Excel文件,人们经常与之打交道。然而,在计算机 领域,文件则被定义为存储在辅助存储器上的一组数据序列,其可以包含任何数据内容。从 概念上来说,文件是数据的抽象和集合。 5.2 文件的类型 1. 文件包括两种类型:文本文件和二进制文件。 (1)文本文件。一般由单一特定编码的字符组成,如UTF-8、GB2312 、ISO-8859-1、 GBK 等编码格式,内容容易统一展示和阅读。文本文件存储常规字符串,由若干文本行组 成,通常每行使用换行符"\n"结尾,其中字符串指的是记事本或其他文本编辑器能够正常 显示、编辑并且能够被人类直接阅读和理解的字符串。 (2)二进制文件。直接由比特0和比特1组成,文件内部数据的组织格式与文件用途 有关。二进制是信息按照非字符但特定格式形成的文件,例如,mp4 jpg 格式的图片文件、 格式的视频文件和mp3格式的音频文件等。二进制文件无法用记事本或其他普通文件编 辑器直接进行编辑,通常也无法被人类直接阅读和理解,需要使用专门的软件进行解码后读 1 32 Python语言程序设计 取、显示、修改和执行。 5.1.3 文件的操作与管理 在Python程序设计中,文件有多种操作和管理方式,文件操作主要包括对文件内容的 读/写操作,这些操作是通过文件对象实现的,通过文件对象可以读写文本文件和二进制文 件。文本文件可以处理各种语言所需的字符,只包含基本文本字符,不包括诸如字体、字号、 颜色等修饰的信息。它可以在文本编辑器和浏览器中显示。即在任何情况下,文本文件都 是可读的。使用其他编码方式的文件即二进制文件,如Word文档、PDF文档、图像文件和 可执行文件等。 1.文件的打开与关闭 Python对文本文件和二进制文件采用统一的操作步骤,即“打开—操作—关闭”,对文 件首先需要将其打开,使得当前程序有权操作这个文件,打开不存在的文件可以创建文件。 打开后的文件处于占用状态,此时,其他程序不能操作这个文件。接下来可以通过一组方法 读取文件的内容或向文件写入内容。文件操作完成后需要将文件关闭,关闭释放对文件的 控制使文件恢复存储状态,此时,别的程序才能够操作这个文件。 图5-1 files.txt的文本内容 在学习文件的打开和关闭操作之前,需要在计算机 的任意盘上创建文件并储入些许文本内容。本书在此以 TXT文本文档为例,编辑的文件名为files.txt,文件的存 储路径为C:\Users\test2\Desktop\files.txt,编辑的文 本内容如图5-1所示。 创建好文本文件后,可以通过open()方法和close() 方法分别对文件进行打开和关闭操作。Python 通过 open()方法打开一个文件,并返回一个操作这个文件的变量,语法形式如下,其中可选参数 <打开模式>的类型见表5-1。 表5-1 open()方法的可选参数<打开模式>的类型 打开模式含 义 "r" 只读模式,如果文件不存在,返回异常FileNotFoundError,默认值 "w" 覆盖写模式,文件不存在则创建,存在则完全覆盖源文件 "x" 创建写模式,文件不存在则创建,存在则返回异常FileExistsError "a" 追加写模式,文件不存在则创建,存在则在源文件最后追加内容 "b" 二进制文件模式 "t" 文本文件模式,默认值 "+" 与r/w/x/a一同使用,在原功能基础上增加同时读写的功能 注意:打开模式使用字符串方式表示,根据字符串定义,单引号或者双引号均可。上述 打开模式中,r' '、'w'、'x'、a' '可以和'b'、t' '、'+'组合使用,形成既表达读写又表达文件模式的 方式。 第5章 文件操作与管理1 33 <文件对象名>=open(<文件路径及文件名>, <打开模式>,<编码格式>) 其中文件路径及文件名是不可省略的,其他参数都可以省略,省略时会使用默认值。 Python用close()方法关闭、释放文件的使用授权,语法形式如下: <文件对象名>.close() 【例5.1】 通过open()和close()方法打开和关闭文件files.txt。 #L5.1 例5.1 f =open(r"C:\Users\test2\Desktop\files.txt", "rt", encoding="UTF-8") print(f.readlines()) f.close() 执行结果: ['文本操作的一个简单实例,\n', '我们需要学会它,\n', '以后肯定用得着。'] 读者在实践中可能会发现当输入的文件路径为C:\Users\Administrator\Desktop\ files.txt时,Python解释器会反馈语法错误SyntaxError。其实这是需要被提醒的一个非常 重要的点,即在输入文件路径及文件名时,要么以r"C:\Users\Administrator\Desktop\ files.txt"的方式,要么以"C:/Users/Administrator/Desktop/files.txt"的方式输入,否则 Python会反馈语法错误。 此外,一些用户在打开文件进行操作之后可能会忘记关闭文件,这样会造成文档信息丢 失等不良后果,因此Python提供了一种名叫上下文管理器的模式来进行文件打开和关闭 操作,以防信息丢失。 【例5.2】 通过上下文管理器打开和关闭文件files.txt。 #L5.2 例5.2 with open(r"C:\Users\test2\Desktop\files.txt", "rt", encoding="UTF-8") as f: print(f.readlines()) 执行结果: ['文本操作的一个简单实例,\n', '我们需要学会它,\n', '以后肯定用得着。'] 编码格式指定文件的编码模式,一般可设定为cp950(繁体中文BIG5)或UTF-8。默认 的编码因操作系统不同而有所不同,如果是Windows简体中文系统,默认的编码是cp936 (GBK),也就是记事本“存储为”界面中显示的ANSI编码。Windows简体中文的记事本默 认使用的是ANSI编码存储文本文件,因此在打开文件时不需要输入编码模式。但是如果 在指定encoding= 'cp936'的情况下去读取用UTF-8编码的文件,那么显示出来的数据内 容有时会出现乱码。由于许多操作系统默认使用UTF-8编码,因此建议将文件保存为 UTF-8编码,而不是ANSI形式。如果文件编码已改为UTF-8,那么读取文件时要加入 encoding= 'UTF-8'编码格式,否则会出现错误。 1 34 Python语言程序设计 2.文件的读写 除了文件的打开与关闭操作,在编写程序的过程中,经常还需要对文件进行读写。 通常来说,与文件打开方式相同,文件读写方式也会根据文本文件或二进制文件的不同 而有所不同。常用的关于读取文件的方法及含义如表5-2所示。 表5-2 常用的文件读取的方法及含义 方 法含 义 文件对象名.read(size=-1) 从文件中读入整个文件内容。参数可选,如果给出,读入前size长 度的字符串或字节流 文件对象名.readline(size= -1) 从文件中读入一行内容。参数可选,如果给出,读入该行前size长 度的字符串或字节流 文件对象名.readlines(hint=-1) 从文件中读入所有行,以每行为元素形成一个列表。参数可选,如 果给出,读入hint行 文件对象名.seek(offset) 改变当前文件操作指针的位置。offset的值:0代表文件开头;2代 表文件结尾 当文件中存储的内容不多时,可以使用read()方法一次性将文本内容读取到文件对象 中,该方法也是Python程序设计中常用于一次性读入文本内容的方法。 【例5.3】 通过read()方法读取文件files.txt中存储的内容。 #L5.3 例5.3 with open(r"C:\Users\test2\Desktop\files.txt", "rt", encoding="UTF-8") as f: contents =f.read() print(contents) 执行结果: 文本操作的一个简单实例, 我们需要学会它, 以后肯定用得着。 当文件中存储的内容过大时,通常采用readline()方法对文件中存储的内容进行读取 操作。readline()方法主要用于从文件中按行读取存储的内容,值得注意的是,当读取的内 容超过文本中存储的行数时,该函数读取到的内容为空。 【例5.4】 通过readline()方法按行读取文件files.txt中存储的内容。 #L5.4 例5.4 with open(r"C:\Users\test2\Desktop\files.txt", "rt", encoding="UTF-8") as f: contents1 =f.readline() contents2 =f.readline() contents3 =f.readline() contents4 =f.readline() print(contents1) print(contents2) print(contents3) print(contents4) 第5章 文件操作与管理1 35 执行结果: 文本操作的一个简单实例, 我们需要学会它, 以后肯定用得着。 readlines()方法和read()方法相似,也是用于一次性将文本内容读入文件对象的方法, 不过readlines()方法读入的文本内容是以列表的形式存储在文件对象中的,而read()方法 则是直接存储在文件对象中。 【例5.5】 通过readlines()方法读取文件files.txt中存储的内容。 #L5.5 例5.5 with open(r"C:\Users\test2\Desktop\files.txt", "rt", encoding="UTF-8") as f: contents =f.readlines() print(contents) 执行结果: ['文本操作的一个简单实例,\n', '我们需要学会它,\n', '以后肯定用得着。'] 在seek()方法的使用中引入了文件读取指针的概念,在文件打开后,对文件的读写有 一个读取指针,当从文件中读入内容后,读取指针将向前进,再次读取的内容将从指针的新 位置开始。比如当使用完read()方法对文件进行读取之后,读取指针将指向文件的末尾, 如果再次使用其他读取函数对文件进行读取的话由于读取指针无法读取到任何内容,因此 返回的结果将为空。此时,seek()方法便可以发挥其作用,移动读取指针,令读取指针指向 文件的其他位置。 【例5.6】 通过seek()方法移动文件读取指针。 #L5.6 例5.6 with open(r"C:\Users\test2\Desktop\files.txt", "rt", encoding="UTF-8") as f: contents =f.readlines() #通过readlines()方法读取文件files.txt 中存储的全部内容 contents1 =f.readlines() #再次调用readlines()方法读取文件files.txt 中存储的内容,将返回一个空列表 print("第一次读取的内容: ", contents) #将读取的全部内容打印到屏幕上 print("再次读取的内容: ", contents1) #将返回的空列表打印到屏幕上 f.seek(0) #将文件指针移动到文件开头 contents1 =f.readlines() #调用readlines()方法读取文件files.txt 中存储的内容 print("读取的内容: ", contents1) #将读取的文件内容打印到屏幕上 执行结果: 1 36 Python语言程序设计 第一次读取的内容: ['文本操作的一个简单实例,\n', '我们需要学会它,\n', '以后肯定用得着。'] 再次读取的内容: [] 读取的内容: ['文本操作的一个简单实例,\n', '我们需要学会它,\n', '以后肯定用得着。'] 除了以上4个常用的关于文件读取的方法之外,从文本文件按行读取内容并进行处理 也是文件读取的一个常用操作,由于文本文件可以看作由行组成的对象,因此可以使用循环 遍历来对文件进行读取和处理操作。 【例5.7】 通过循环读取文件files.txt中存储的内容。 #L5.7 例5.7 with open(r"C:\Users\test2\Desktop\files.txt", "rt", encoding="UTF-8") as f: for line in f: #使用for 循环读取文件files.txt 中存储的内容 print(line) # 将for 循环按行读取到的内容打印到屏幕上,也可进行其他的处理 操作 执行结果: 文本操作的一个简单实例, 我们需要学会它, 以后肯定用得着。 接下来将介绍关于文件写的方法,常用的文件写的方法及其含义如表5-3所示。 表5-3 常用的文件写的方法及含义 方 法含 义 文件对象名.write(str) 向文件写入一个字符串或字节流 文件对象名.writelines(lists) 将一个字符串列表写入文件 write()方法用于向指定文件中写入字符串,每次写入后,都会记录一个写入指针。该 方法可以反复调用,将在写入指针后分批写入内容,直至文件被关闭。 【例5.8】 通过write()方法向指定文件中写入内容。 #L5.8 例5.8 with open(r"D:\example.txt", "w", encoding="UTF-8") as f: f.write("读者,您好!\n") #向指定文件example.txt 中写入字符串“读者,您好!” f.write("这是文件写的一个示例程序。") #向指定文件example.txt 中追加写入字符串“这是文件写的一个示例程序。” 图5-2 使用write()方法写入的内容 以上语句运行后将在D盘目录下生成一个文件example.txt,并写入如图5-2所示的内 容。当使用write()方法时,要显式地使用换行符"\n" 对写入的文本进行换行,如果不进行换行的话,每次写 入的字符串会被连接起来。 writelines()方法用于直接将列表类型的各元素连 第5章 文件操作与管理1 37 接起来写入文件。 【例5.9】 通过writelines()方法向指定文件中写入内容。 #L5.9 例5.9 lists =["1, 2, 3\n", "读者,您好!\n", "这是文件写的另一个示例程序。\n"] with open(r"D:\example1.txt", "w", encoding="UTF-8") as f: f.writelines(lists) #向文件example1.txt 中写入lists 列表 以上语句运行后将在D盘目录下生成一个文件example1.txt,并写入如图5-3所示的 内容。 图5-3 使用writelines()方法写入的内容 5.2 os模块的使用 OS,操作系统(operatingsystem)的缩写形式。很明显,os模块可以直接对操作系统进 行操作,因此,os模块是Python语言中相当重要的一个模块。使用os模块,可以访问操作 系统提供的功能。此外,通过使用os模块中提供的接口,还可以实现跨平台访问。本节将 介绍os模块的系统操作、对目录的增删改查操作及path模块中基本方法的使用。 5.2.1 os模块的系统操作 在Python语言中,os模块用于系统操作的基本方法有4个,这4个基本方法及含义如 表5-4所示。 表5-4 os模块用于系统操作的基本方法及含义 方 法含 义 os.sep 用于系统路径的分隔符,其中Windows系统的分隔符为“\”或“\\”;Linux 类系统如Ubuntu的分隔符是“/” os.name 指示当前使用的工作平台,比如对于Windows用户,它是“nt”;对于Linux 或Unix用户,它是“posix” os.getenv(环境变量名称) 读取环境变量 os.getcwd() 获取当前的工作路径 【例5.10】 通过os模块的4个基本方法查看当前操作系统的相关信息。 #L5.10 例5.10 import os #导入os 模块 print(os.sep) #打印当前系统的分隔符 1 38 Python语言程序设计 print(os.name) #打印当前正在使用的工作平台信息 print(os.getenv("path")) #打印出系统当前配置的环境变量(每个人的配置可能有所不同) print(os.getcwd()) #打印当前的工作路径 执行结果: \n t H:\Anaconda3\envs\tensorflow; H:\Anaconda3\envs\tensorflow\Library\usr\bin; H:\ Anaconda3\envs\tensorflow\Library\bin G:\PythonProjects\figure_examples 5.2.2 对目录和文件的管理 对目录的增删改查操作是Python程序设计中必不可少的一部分,在os模块中用于对 目录进行增删改查操作的基本方法及含义如表5-5所示。 表5-5 os模块中用于对目录进行增删改查操作的基本方法及含义 方 法含 义 os.listdir() 返回指定目录下的所有目录和文件名 os.mkdir(dirname) 创建一个目录文件。若目录已经存在,则创建目录失败 os.rmdir(dirname) 删除一个空目录。若目录中有文件则无法删除 os.makedirs(dirname) 可以生成多层递归目录。若目录全部存在,则创建目录失败 os.removedirs(dirname) 可以删除多层递归的空目录,若目录中有文件则无法删除 os.remove(filename) 删除filename参数指定的文件 os.chdir() 改变当前目录,到指定目录中 os.rename() 重命名目录名或者文件名。若重命名后的文件名已存在,则重命名失败 由于表5-5中列出的方法的使用流程基本相同,因此仅以listdir()和mkdir()方法为 例,剩余的方法请自己实践完成。 【例5.11】 通过os模块中的listdir()和mkdir()方法实现对目录的操作。 #L5.11 例5.11 import os #导入os 模块 print(os.listdir(r"G:\\")) #打印出G 盘下的所有目录和文件名 os.mkdir(r"G:\examples") #在G 盘下创建examples 目录 以上语句运行后将在屏幕上打印出G 盘下的所有目录和文件名,并在G 盘下创建了 examples目录文件。 【例5.12】 通过os模块中的remove()方法实现对文件的删除操作。 #L5.12 例5.12 import os #导入os 模块 第5章 文件操作与管理1 39 file ="testfile.txt" if os.path.exists(file): #检查当前路径下testfile.txt 是否存在 os.remove(file) #如果文件存在则删除该文件 else: print(file+"文件未找到!") 【例5.13】 通过os模块中的system()方法管理目录。 #L5.13 例5.13 import os #导入os 模块 my_path =os.path.dirname(__file__) #取得当前路径 os.system("cls") #清除屏幕 os.system("mkdir testdir") #创建testdir 目录 os.system("copy testfile.txt testdir\copytestfile.txt")# 复制文件 file =my_path +"\testdir\copytestfile.txt" os.system("notepad" +file) #以记事本方式打开copytestfile.txt 5.2.3 path模块中基本方法的使用 path,汉语翻译为路径,顾名思义,path模块与目录或文件路径的操作相关。在path模 块中用于对文件或目录路径进行操作的基本方法及含义如表5-6所示。 表5-6 path模块中用于对文件或路径进行操作的基本方法及含义 方 法含 义 os.path.exists(path) 判断文件或者目录是否存在,存在则返回True,否则返回False os.path.isfile(path) 判断是否为文件,是文件则返回True,否则返回False os.path.isdir(path) 判断是否为目录,是目录则返回True,否则返回False os.path.basename(path) 返回文件名 os.path.dirname(path) 返回文件路径 os.path.getsize(name) 获得文件大小 os.path.abspath(name) 获得文件或目录的绝对路径 os.path.join(path,name) 连接路径与文件/目录 【例5.14】 通过path模块中的方法实现对目录或文件的操作。 #L5.14 例5.14 import os #导入os 模块 path =r"G:\\" #定义path 路径 os.mkdir(r"G:\examples") #在G 盘下创建examples 目录,如果G 盘下存在examples 目录,则先删除再运行 print(os.path.exists(r"G:\examples")) #判断G 盘下是否存在examples 目录 print(os.path.isfile (r"G:\examples")) #判断G 盘下的examples 是否为文件 print(os.path.isdir (r"G:\examples")) #判断G 盘下的examples 是否为目录 1 40 Python语言程序设计 print(os.path.basename (r"G:\examples")) #打印G 盘下的examples 的文件名 print(os.path.dirname (r"G:\examples")) #打印G 盘下的examples 的父路径 print(os.path.getsize (r"G:\examples")) #打印G 盘下的examples 目录的大小 print(os.path.abspath (r"G:\examples")) #打印G 盘下的examples 目录的绝对路径 new_path =os.path.join(path, "examples") #连接path 路径和examples 目录,从而形成新的路径 print("新的路径为: ",new_path) 执行结果: True False True examples G:\ 0 G:\examples 新的路径为: G:\\examples 5.3 数据的处理 数据的存储和处理是Python程序设计中必不可少的一个模块,本节将介绍数据的组 织维度以及一维数据(如列表)、二维数据(如表格数据)和多维数据(如嵌套字典)的存储与 处理。 5.3.1 数据的组织维度 数据在被计算机处理前,都需要一定的组织形式来表明数据之间的逻辑和关系,而不同 的组织形式也就形成了不同的“数据的组织维度”。根据数据组织形式的不同,可以将数据 的维度分为一维数据、二维数据和多维数据。 5.3.2 一维数据的存储与处理 一维数据(如C/C++语言中的一维数组)是最简单的数据组织形式,由于采用线性关系 的方式进行组织,所以在Python语言中主要采用list列表的形式表示。 一维数据的文件存储方式有多种,通常采用拼接逗号作为分隔元素的方式对其进行存 储。使用逗号分隔方式存储的文件叫作CSV(comma-separatedvalues,逗号分隔值)文件, 在CSV 文件中,各元素间被逗号分隔,形成一行数据。在对CSV 文件中存储的一维数据进 行处理时,需要以CSV 格式读入和输出。 常见的一维数据如姓名列表: data =["张三", "李四", "王五"] 【例5.15】 使用CSV 格式对一维数据进行读写处理。 #L5.15 例5.15 data =["张三","李四","王五"] #定义一维数据