原文链接:http://www.juzicode.com/archives/621
文件读写是计算机语言无法回避的话题,这篇文章将介绍文件的基本读写操作。通常文件分为文本文件和二进制文件,Python也支持这2种文件的读写操作。
1 打开文件
打开文件使用open()函数:文件对象fileobj=open(‘文件名称’,‘打开模式’),如果打开文件成功,就会创建一个文件对象,后面的读出、写入和关闭就在该对象上进行。
文件的打开模式有下表的几种模式,其中是否带字母“b”决定了访问文件的方式是采用文本方式访问还是二进制方式访问(带字母“b”),如果采用文本方式访问时,需要指定文件的编码方式,默认跟随系统设置的编码方式;二进制访问就是获取文件的每个字节的二进制数值,不存在类似文本的编码方式。
打开模式 | 文件类型 | 方式 | 对已有文件影响 | 如果文件不存在 | 备注 |
r | 文本 | 只读 | 无 | 抛异常 | write等方法不可用 |
rb | 二进制 | 只读 | 无 | 抛异常 | write等方法不可用 |
r+ | 文本 | 读写 | 追加 | 抛异常 | |
rb+ | 二进制 | 读写 | 追加 | 抛异常 | |
w | 文本 | 只写 | 覆盖并新建 | 新建 | read等方法不可用 |
wb | 二进制 | 只写 | 覆盖并新建 | 新建 | read等方法不可用 |
w+ | 文本 | 读写 | 覆盖并新建 | 新建 | 因为覆盖原来文件,read等方法获取到原文件的内容 |
wb+ | 二进制 | 读写 | 覆盖并新建 | 新建 | 因为覆盖原来文件,read等方法获取到原文件的内容 |
a | 文本 | 追加 | 追加到最后 | 新建 | read等方法不可用 |
ab | 二进制 | 追加 | 追加到最后 | 新建 | read等方法不可用 |
a+ | 文本 | 读写 | 追加到最后 | 新建 | |
ab+ | 二进制 | 读写 | 追加到最后 | 新建 |
下面这个例子试图以文本只读模式打开一个不存在的文件,会出现抛异常,提示文件不存在“No such file or directory”:
fileobj=open('example-r1.txt','r')
print('fileobj',fileobj)
==========结果==========
Traceback (most recent call last):
File "E:\juzicode\py3study\m02-文件\open-打开文件.py", line 12, in <module>
fileobj=open('example-r1.txt','r')
FileNotFoundError: [Errno 2] No such file or directory: 'example-r1.txt'
如果使用“w”模式打开文件,试图调用read()方法会导致异常:
下面的这个例子是用“r”和“rb”模式打开2个文件,从打印文件对象的信息可以看到,“example-r1.txt”是用“r”模式打开,调用open()函数时没有显式说明编码方式,从这个对象信息中可以看到默认的编码方式是cp936,这是跟随中文操作系统默认的GBK编码方式。而打开“example-r2.txt”文件是二进制方式,是不需要表明编码方式的。
fileobj=open('example-r1.txt','r')
print('fileobj',fileobj)
fileobj=open('example-r2.txt','rb')
print('fileobj',fileobj)
==========结果==========
-----欢迎来到www.juzicode.com
-----公众号: juzicode/桔子code
fileobj <_io.TextIOWrapper name='example-r1.txt' mode='r' encoding='cp936'>
fileobj <_io.BufferedReader name='example-r2.txt'>
2 关闭文件
使用完文件后要使用文件对象fileobj.close()方法关闭文件。
fileobj=open('example-r1.txt','r')
print('fileobj',fileobj)
fileobj.close() #关闭文件
当然在Python中还提供了一种比较“优雅”的打开文件的方式,不需要人为的显式调用close()方法关闭文件,使用with…as…语句:
with open('example-r2.txt','r') as fileobj:
print('fileobj',fileobj)
fileobj.read()
print('fileobj',fileobj)
fileobj.read()
==========结果==========
fileobj <_io.TextIOWrapper name='example-r2.txt' mode='r' encoding='cp936'>
fileobj <_io.TextIOWrapper name='example-r2.txt' mode='r' encoding='cp936'>
Traceback (most recent call last):
File "E:\juzicode\py3study\m02-文件\close-关闭文件2.py", line 17, in <module>
fileobj.read()
ValueError: I/O operation on closed file.
从上面的例子可以看出在with…as…缩进的代码块中,使用fileobj的read()方法是没有问题的,但是在with..as语句之后,再使用fileobj.read()方法时,抛ValueError异常提示文件已关闭,说明在with…as语句之外文件对象已经关闭了。
3 读文件
方法 | 用途 | 备注 |
read() | 尽可能多读出文件内容 | |
readline() | 每次读一行 | |
readlines() | 读所有行,读出内容为换行符为间隔分割的list |
下面这个例子就是用3种方法分别读出一个有4行文本内容的文件:
with open('example-r1.txt','r') as fileobj:
content=fileobj.read()
print('read()方法:\n',content)
with open('example-r1.txt','r') as fileobj:
content=fileobj.readline()
print('readline()方法:\n',content)
with open('example-r1.txt','r') as fileobj:
content=fileobj.readlines()
print('readlines()方法:\n',content)
==========结果==========
read()方法:
www.juzicode.com
juzicode.com
公众号: 桔子code
公众号: juzicode
readline()方法:
www.juzicode.com
readlines()方法:
['www.juzicode.com\n', 'juzicode.com\n', '公众号: 桔子code\n', '公众号: juzicode']
4 写文件
方法 | 用途 | 备注 |
write() | 写入内容 | |
writelines() | 写入list内容,不会在元素之间自动添加换行符。 |
【注意】文件对象不存在writeline()方法!
写文本文件的例子:
对比readlines()方法,writelines()不会进行“逆操作”在list元素后添加换行符。
5 追加模式读出文件
用追加模式“a+”打开文件时,使用read()方法读出文件后再打印文件内容,发现“获取”到的值为空:
with open('example-a3.txt','a+',encoding='utf8') as fileobj:
content=fileobj.read()
print('read():\n',content)
==========结果==========
read():
#打印的内容为空
使用“a”模式打开文件时调用read()方法会导致抛异常,而“a+”模式下read()方法可以使用只是没有得到预期的内容。是因为追加模式打开文件后,文件指针实际指向了文件的最后,所以read()方法获取不到文件内容,打开文件后就使用tell()方法可以看到文件指针实际已经指向了文件的最后,要获取文件内容可以使用seek(0)方法将文件指针指到文件的开头,再使用read()方法读出文件内容:
with open('example-a3.txt','a+',encoding='utf8') as fileobj:
posi = fileobj.tell() #获取当前文件指针位置
print('tell():',posi)
fileobj.seek(0) #文件指针指向开始位置
content=fileobj.read()
print('read():\n',content)
==========结果==========
tell(): 47
read():
www.juzicode.com
微信公众号: 桔子code