第7章文件操作肖川cxiao@fudan.edu.cnoutline文件基本操作文本文件基本操作二进制文件操作文件为了长期保存数据以便重复使用、修改和共享,必须将数据以文件的形式存储到外部存储介质(如磁盘、U盘、光盘等)或云盘中。管理信息系统是使用数据库来存储数据的,而数据库最终还是要以文件的形式存储到硬盘或其他存储介质上,应用程序的配置信息往往也是使用文件来存储的,图形、图像、音频、视频、可执行文件等等也都是以文件的形式存储在磁盘上的。因此,文件操作在各类应用软件的开发中均占有重要的地位。文件种类按文件中数据的组织形式把文件分为文本文件和二进制文件两类。文本文件二进制文件文件种类——文本文件(1)文本文件文本文件存储的是常规字符串,由若干文本行组成,通常每行以换行符'\n'结尾。常规字符串是指记事本或其他文本编辑器能正常显示、编辑并且人类能够直接阅读和理解的字符串,如英文字母、汉字、数字字符串。文本文件可以使用字处理软件如gedit、记事本进行编辑。文件种类——二进制文件(2)二进制文件二进制文件把对象内容以字节串(bytes)进行存储,无法用记事本或其他普通字处理软件直接进行编辑,通常也无法被人类直接阅读和理解,需要使用专门的软件进行解码后读取、显示、修改或执行。常见的如图形图像文件、音视频文件、可执行文件、资源文件、各种数据库文件、各类office文档等都属于二进制文件。文件基本操作IPO键盘显示器程序input(.)print(.)文件readline(.)等文件write(.)等输入设备输出设备文件基本操作文件对象名=open(文件名[,打开方式[,缓冲区]])(1)文件名指定了被打开的文件名称。(2)打开模式指定了打开文件后的处理方式,见表7-1。(3)缓冲区指定了读写文件的缓存模式。0表示不缓存,1表示缓存,如大于1则表示缓冲区的大小。默认值是缓存模式。(4)open()函数返回1个文件对象,该对象可以对文件进行各种操作。例如:f1=open('file1.txt','r')f2=open('file2.txt','w')文件基本操作文件打开方式r:若文件不存在,则出错;若文件存在,则打开该文件。w:若文件不存在,则创建空文件;若文件存在,则清空文件内容。a:若文件不存在,则创建空文件;若文件存在,则追加文件内容。文件基本操作文件常用属性属性说明Closed判断文件是否关闭,若文件被关闭,则返回TrueMode返回文件的打开模式Name返回文件的名称文件基本操作文件对象常用方法方法说明flush()把缓冲区的内容写入文件,不关闭文件close()把缓冲区的内容写入文件,关闭文件,释放文件对象read([size])从文件中读取size个字节的内容作为结果返回,如果省略size则表示一次性读取所有内容readline()从文本文件中读取一行(包括换行符)内容作为结果返回readlines()把文本文件中的每行(包括换行符)作为字符串插入列表中,返回该列表seek(offset[,whence])把文件指针移动到新的位置,offset表示相对于whence的位置。whence为0表示从文件头开始计算,1表示从当前位置开始计算,2表示从文件尾开始计算,默认为0tell()返回当前文件指针的位置truncate([size])删除从当前指针位置到文件末尾的内容。如果指定了size,则不论指针在什么位置都只留下前size个字节,其余的删除write(s)把字符串s的内容写入文件writelines(s)把字符串列表写入文本文件,不在每个串后添加换行符文本文件基本操作写文件例1:向文本文件中写入内容。分别执行多次,结果有什么不同?文本文件基本操作更建议这样写:使用with自动关闭资源。可以在代码块执行完毕后还原进入该代码块时的现场。不论何种原因跳出with块,总能保证文件被正确关闭。写文件执行结果有什么不同?“保存文件”对话框模块tkinter.filedialog函数asksaveasfilename()这个函数返回一个文件名如果对话框被用户取消,那么返回None写文件读文件读取并显示文本文件的前5个字符。(Python3)读文件例3:读取并显示文本文件所有行。读文件或者可以这样写:“打开文件”对话框模块tkinter.filedialog函数askopenfilename()这个函数返回一个文件名如果对话框被用户取消,那么返回None读文件示例:拷贝文本文件用户指定源文件及副本文件seek(.)方法例4:移动文件指针。Python2.x和Python3.x对于seek()方法的理解和处理是一致的,即将文件指针定位到文件中指定字节的位置。但是由于对中文的支持程度不一样,可能会导致在Python2.x和Python3.x中的运行结果有所不同。例如下面的代码在Python3.4.2中运行,当遇到无法解码的字符会抛出异常。移动文件指针s='中国山东烟台SDIBT'fp=open(r'D:\sample.txt','w')fp.write(s)11fp.close()fp=open(r'D:\sample.txt','r')print(fp.read(3))中国山fp.seek(2)2print(fp.read(1))国fp.seek(13)13print(fp.read(1))Dfp.seek(15)15print(fp.read(1))Bfp.seek(3)3print(fp.read(1))出错信息UnicodeDecodeError:'gbk'codeccan'tdecodebyte0xfainposition0:illegalmultibytesequence例5:假设文本文件data.txt中每行是一个整数。读取data.txt中所有整数,将其按升序排序后再写入文本文件data_asc.txt中。文本文件基本操作例6:假设已有程序文件demo6.py,由此生成文件demo6_new.py,其中的内容与demo6.py一致,但是在每行的行尾加上了行号。文本文件基本操作例7:Python程序中代码复用度检测。FindLongestReuse.py二进制文件操作7.3二进制文件操作案例精选数据库文件、图像文件、可执行文件、音视频文件、Office文档等等均属于二进制文件。对于二进制文件,不能使用记事本或其他文本编辑软件进行正常读写,也无法通过Python的文件对象直接读取和理解二进制文件的内容。必须正确理解二进制文件结构和序列化规则,才能准确地理解二进制文件内容并且设计正确的反序列化规则。所谓序列化,简单地说就是把内存中的数据在不丢失其类型信息的情况下转成对象的二进制形式的过程,对象序列化后的形式经过正确的反序列化过程应该能够准确无误地恢复为原来的对象。Python中常用的序列化模块有struct、pickle、json、marshal和shelve,其中pickle有C语言实现的cPickle,速度约提高1000倍,应优先考虑使用。7.3.1使用pickle模块写入文件:importpicklef=open('sample_pickle..dat','wb')n=7i=13000000a=99.056s='中国人民123abc'lst=[[1,2,3],[4,5,6],[7,8,9]]tu=(-5,10,8)coll={4,5,6}dic={'a':'apple','b':'banana','g':'grape','o':'orange'}try:pickle.dump(n,f)#表示后面将要写入的数据个数pickle.dump(i,f)#把整数i转换为字节串,并写入文件pickle.dump(a,f)pickle.dump(s,f)pickle.dump(lst,f)pickle.dump(tu,f)pickle.dump(coll,f)pickle.dump(dic,f)except:print'写文件异常!'#如果写文件异常则跳到此处执行f.close()7.3.1使用pickle模块读取二进制文件:importpicklef=open('sample_pickle.dat','rb')n=pickle.load(f)#读出文件的数据个数i=0whilein:x=pickle.load(f)printxi=i+1f.close()7.3.2使用struct模块例:使用struct模块写入二进制文件:importstructn=1300000000x=96.45b=Trues='a1@中国'sn=struct.pack('if?',n,x,b)#把整数n、浮点数x、布尔对象b依次转换为字节串f=open('sample_struct.dat','wb')f.write(sn)#写入字节串f.write(s)#字符串可直接写入f.close()7.3.2使用struct模块例:使用struct模块读取二进制文件。importstructf=open('sample_struct.dat','rb')sn=f.read(9)tu=struct.unpack('if?',sn)#从字节串sn中还原出1个整数、1个浮点数和1个布尔值,并返回元组print(tu)n=tu[0]x=tu[1]bl=tu[2]print'n=',nprint'x=',xprint'bl=',bls=f.read(9)f.close()print's=',s7.4文件级操作如果仅需要对文件内容进行读写,可以使用7.1节中介绍的文件对象;如果需要处理文件路径,可以使用os.path模块中的对象和方法;如果需要使用命令行读取文件内容可以使用fileinput模块;创建临时文件和文件夹可以使用tempfile模块;另外,Python3.4的pathlib模块提供了大量用于表示和处理文件系统路径的类。7.4.1os与os.path模块os模块常用的文件处理函数函数使用说明access(path,mode)按照mode指定的权限访问文件open(path,flags,mode=0o777,*,dir_fd=None)按照mode指定的权限打开文件,默认权限为可读、可写、可执行chmod(path,mode,*,dir_fd=None,follow_symlinks=True)改变文件的访问权限remove(path)删除指定的文件rename(src,dst)重命名文件或目录stat(path)返回文件的所有属性fstat(path)返回打开的文件的所有属性listdir(path)返回path目录下的文件和目录列表startfile(filepath[,operation])使用关联的应用程序打开指定文件7.4.1os与os.path模块os.path模块常用的文件处理函数函数名称使用说明abspath(path)返回绝对路径dirname(p)返回目录的路径exists(path)判断文件是否存在getatime(filename)返回文件的最后访问时间getctime(filename)返回文件的创建时间getmtile(filename)返回文件的最后修改时间getsize(filename)返回文件的大小isabs(path)、isdir(path)、isfile(path)判断path是否为绝对路径、目录、文件split(path)对路径进行分割,以列表形式返回splitext(path)从路径中分割文件的扩展名splitdrive(path)从路径中分割驱动器的名称walk(top,func,arg)遍历目录7.4.1os与os.path模块importosimportos.pathos.path.exists('test1.txt')False