Python文件处理
当程序执行完毕之后,所有存储在内存中的数据都会消失,这时如果需要将执行结果存储在不会挥发的存储介质上(如磁盘等),就必须通过文件模式来加以保存。
认识文件
文件(File)是计算机中数字、数据和信息的集合,是一种存储数据的单位,也是在磁盘驱动器上存储数据的重要形式,这些数据以字节的方式存储,可以是一份报告、一张图片或一个执行程序,因而包括数据文件、程序文件或可执行文件等格式。使用文件存取数据是数据加工、处理和存储中非常重要的一环。
在程序的运行过程中,所有的数据都存储在内存中,一旦程序结束,之前输入的数据就会全部消失。在程行执行的过程中,如果要将加工、处理或计算得到的数据永久保存下来,就必须将数据写入文件并存放在非挥发性(Non-Volatile)的存储介质中,例如硬盘。每个文件都必须有文件名(File Name),文件名分为“主文件名”与“扩展名”,中间以句点“.”分隔,“扩展名”的功能在于记录文件的类型。
例如.cpp表示是C++的源代码程序文件,.py表示是Python语言的源代码程序文件。通过这样的命名方式可以让我们清楚地分辨出文件名及其文件类型,如下所示:
主文档名.扩展名
文件的读与写
当程序执行完毕之后,所有存储在内存的数据都会消失,如果要将执行的结果存储在硬盘等非挥发的存储介质上,就必须将执行的结果以文件形式存储在硬盘等存储设备中。
文件的写入
Python在处理文件的读取与写入时都是通过文件对象,因此,无论是进行文件的写入或读取操作,第一项工作就是调用Python的内部函数open()来创建文件对象。所谓文件对象(File Object),就是一个提供存取文件的接口,它并非实际的文件。当打开文件之后,必须通过“文件对象”执行读(Read)或写(Write)的操作。
open()函数的语法如下:
open(file, mode)
- file:以字符串来指定想要打开文件的路径和文件名。
- mode:以字符串指定打开文件的存取模式。
如果调用open()创建文件对象的操作成功了,就会返回文件对象;如果创建文件失败了,就会发生错误。当以读取模式”r”打开文件时,如果该文件不存在,就会发生错误。
例如,下面的程序语句是以读取模式打开一个名称为C:\test.txt的文件,如果通过这个文件的路径找不到这个文件,就会发生FileNotFoundError的错误信息,这个信息告知用户所打开的文件或目录不存在:
file1=open("C:\\test.txt","r")
FileNotFoundError: [Errno 2] No such file or directory: 'C:\\test.txt'
刚才谈到的情况是以读取模式打开文件,当文件不存在时会发生错误。如果以写入模式打开文件,第一次打开该文件,而该文件不存在,这个时候系统就会自动以该名称创建新文件,而不会发生类似于读取模式找不到文件的错误。
例如,以下程序语句是以写入模式打开一个名称为C:\test.txt的文件,如果通过这个文件路径找不到这个文件,就会以该名称创建文件,并创建一个文件对象,再赋值给变量file1:
file1=open("C:\\test.txt","w")
大家要特别留意,调用open()函数打开文件时,所指定的文件路径必须以转义字符“\”来表示“\”,例如:
file1=open("C:\\lab\\test.txt"."r")
如果我们觉得上述路径表示方式不实用,也可以在绝对路径前面加r,来告知编译程序系统r后随的路径字符串是原始字符串,如此一来,原先用“\”来表示“\”的方式就可以简化为如下表示方式:
file1=open(r"C:\lab\test.txt"."r")
也就是说,对于文本文件而言,要将数据写入文件中,必须事先调用open()方法创建新文件,再使用文件对象所提供的write()方法将文字写入文件,最后调用close()方法关闭文件。
注意写入文件时会从文件指针当前所在的位置开始,因此写入文件时,必须指定存取模式。文件指针用来记录文件当前写入或读取到了哪一个位置。
# 创建字符串内容。
yeats = '''
若问前世因
今生受者是
若问来世果
今生作者是
'''
# 调用open()函数时必须把文件对象赋值给变量fn,以便进行文件的存储。第一个参数是要创建文件使用的文件名,此处创建文本文件,第二个参数mode为wt,即以字符串方式表示“以文本格式写入”。
fn = open('phrase.txt', 'wt')
# 以fn(文件对象)调用write()方法并传入参数。
fn.write(yeats)
# 以fn调用close()方法关闭文件,如此才能将位于缓冲区的内容全部写入文件,未使用此方法会让创建的文件是空的。
fn.close()
文件的读取
相对于写入文件的步骤,要读取文件的数据,首先必须调用open()方法打开指定的文件,接着使用文件对象所提供的read()、readline()或readlilnes()方法从文件读取数据,最后调用close()方法关闭文件。
前面曾提醒大家,读取文件和写入文件有不同之处,如果以读取模式打开文件,当文件不存在时,会发生找不到文件的错误。 为了避免这类错误的发生,可以在打开文件之前以os.path模块所提供的isfile(file)函数来检查指定文件名的文件是否存在。如果文件存在,就返回True,否则返回False。
下面的范例程序会先行判断文件是否存在,如果存在,就打印出文件中的所有内容。
import os.path #导入os.path
#调用isfile()方法先行判断文件是否存在
#如果文件存在,就打印出文件的内容
if os.path.isfile("resume.txt"):
fb=open("resume.txt","r")
for word in fb:
print(word)
#如果文件不存在,就输出文件不存在的提示信息
else:
print("指定要打开的文件不存在!")
当文件创建之后,就可以调用read()、readline()或readlines()方法来读取文件。下面来认识这三个方法。
- read()方法
调用read()方法读取数据会从文件当前指针所在的位置一个字符一个字符去读取,读取完指定个数的字符之后,就返回该字符串,其语法如下:
read(n)
在下面的范例程序中,会以”r”的文件存取模式打开文件,文件指针会指向文件的起始处,从文件的开头读取文件的所有数据内容,再以字符串的数据类型赋值给变量text,这个时候系统会将文件指针从原先的文件起始处移到文件的结尾处。接下来,程序设计人员就可以调用print函数将所读取的文件内容打印输出,最后调用close()方法关闭文件。
#调用open()方法打开指定的文本文件
fb=open("introduct.txt","r")
#调用read()方法读取文件的内容
text=fb.read()
#输出字符串变量text的内容
print(text)
#调用close()方法关闭文件
fb.close()
上面的read()方法没有指定要读取的字符数,其实我们也可以在read()方法中传入一个参数来告知要读取几个字符。
接下来的范例程序仍以上述文本文件为例,一开始文件指针指向文件的起始处,在读取所指定的12个字符后,文件指针会移到文件的该12个字符之后,接着读取下一条程序语句所指定的字符数,一旦不再需要读取文件,就可以使用close()方法关闭文件。
#调用open()方法打开指定的文本文件
fb=open("introduct.txt","r")
#调用read(n)方法读取文件的内容
text=fb.read(12)
#输出字符串变量text的内容
print(text)
#调用read(n)方法读取文件的内容
text=fb.read(13)
#输出字符串变量text的内容
print(text)
#调用close()方法关闭文件
fb.close()
我们知道文件指针指向文件当前要写入或读取的位置,前面两个范例程序中的文件指针的移动都是由系统自行移动的,如果程序设计人员想要通过程序指令把文件指针移到指定的位置,就需要调用seek(offset)方法,这个方法的功能是将文件指针移到第offset+1个字节,例如seek(0)表示将文件指针移到文件的第一个字节位置,也就是文件的起始处。
在下面的范例程序中,我们来看一看seek()的主要作用。
import os.path #导入os.path
import sys
#调用isfile()方法先行判断文件是否存在
#如果文件存在,就取消复制工作
if os.path.isfile("introduct1.txt"):
print("指定要打开的文件已存在,不要进行复制。")
sys.exit()
else:
#调用open()方法打开指定的文件,文件打开模式为"r"
fb1=open("introduct.txt","r")
#调用open()方法打开指定的文件,文件打开模式为"w"
fb2=open("introduct1.txt","w")
text=fb1.read() #调用read()方法读取文件的内容
text=fb2.write(text) #调用write()方法写入文件
print("文件复制工作完成,请打开introduct1.txt进行查看。")
fb1.close() #调用close()方法关闭文件
fb2.close() #调用close()方法关闭文件
- readline()方法 read()方法是一次读取一个字符,但是readline()方法可以整行读取,并将整行的数据内容以字符串的方式返回,如果所返回的是空字符串,就表示已读到文件的末尾。
以下程序语句就是调用readline()方法以一次一次读取的方式将文件内容逐笔读取再输出。
obj=open("chapter.txt",r)
line=obj.readline()
while True:
print(line)
line=obj.readline()
obj.close()
上面的程序语句也可以使用for循环来改写,可以得到相同的输出结果。
obj=open("chapter.txt",r) #打开文件
for line in obj:
print(line)
obj.close()
- readlines()方法 还有一个readlines()方法可以帮助用户读取文件,这个方法会一次读取文件的所有行,再以列表类型返回所有行。
下面用简单的例子进行说明。
with open('introduct.txt', 'rt') as foin:
total = foin.readlines()#一次读取所有行
#获取行数,再用for循环读取并输出
print('行数:', len(total))
for line in total:
print(line, end = '')
二进制文件
计算机上的数据并非只有文本类型,常见的数据格式还有图像、音乐或者经过编译的EXE文件等,这些数据无法以文本类型的方式来处理,而必须以其他的数据格式来处理。如果要创建二进制文件,就在open()方法的mode参数中加入“b”,即表示二进制,否则会引发错误,而内部函数bytearray()用于读取二进制数据。
tmp = bytearray(range(8))
#二进制数据的写入
with open('bytedata', 'wb') as fob:
fob.write(tmp)
#二进制数据的读取
with open('bytedata', 'rb') as fob:
fob.read(3)
print(type(tmp))
print('二进制:', tmp)