目录
1.打开文件
要打开文件,可以使用函数open,它位于自动导入的模块io中。函数open将文件名作为唯一必不可少的参数,并返回一个文件对象。
f = open('test.txt')
如果文件位于其他地方,可以指定完整的路径。如果文件不存在将抛出异常。如果通过写入文本来创建文件,可以使用函数open的第二个参数文件模式。open函数常见的文件模式,主要有:
值 | 描述 |
r | 读取模式,默认值 |
w | 写入模式 |
x | 独占写入模式 |
a | 附加模式 |
b | 二进制模式,与其他模式结合使用 |
t | 文本模式,默认值,与其他模式结合使用 |
+ | 读写模式,与其他模式结合使用 |
显式地指定读取模式的效果与根本不指定模式相同;写入模式让我们能够写入文件,并在文件不存在时创建它;独占写入模式更近一步,在文件已经存在时引发FileExistsError异常;在写入模式下打开文件时,既有内容将被删除,并从文件开头处开始写入;如果要在既有文件末尾继续写入,可使用附加模式。
‘+’可与任何其他模式结合起来使用,表示既可读取也可写入。需要注意的是,‘r+’和‘w+’之间有一个重要的区别:后者截断文件,而前者不会这样做。
默认模式为‘rt’,这意味着将把文件视为经过编码的Unicode文件,因此将自动执行编码和解码,且默认为UTF-8编码。要指定其他编码和Unicode错误处理策略,可使用关键字参数encoding和errors。如果文件包含非文本的二进制数据,如声音剪辑片段或图像,可以使用二进制模式(‘rd’)。
2.文件的基本方法
本节介绍文件对象的一些基本方法以及其他类似于文件的对象(有时称为流)。
2.1 读取和写入
文件最重要的功能是提供和接收数据。如果有一个名为f的类似于文件的对象,可使用f.write来写入数据,还可使用f.read来读取数据。每当调用f.write(string)时,你提供的字符串都将写入到文件中即有内容的后面。
f = open('test.txt', 'w')
res1 = f.write('hello')
res2 = f.write(' world!')
print('写入成功的字符数:', res1, res2)
f.close()
f = open('test.txt', 'r')
print(f.read(4))
print(f.read())
输出结果如下:
写入成功的字符数: 5 7
hell
o world!
调用write方法的返回值是成功写入的字符个数。使用完文件后,调用方法close关闭文件。读取只需告诉流我们读取多少个字符,二进制模式下是多少字节。首先,指定了要读取多少(4)个字符,接下来,读取了文件中余下的全部内容(不指定要读取多少个字符)。
2.2 使用管道重定向输出
在bash等shell中,可依次输入多个命令,并使用管道将它们链接起来。例如:
cat test.txt | python testscrip.py | sort
这条管道线包含三条命令:
- cat test.txt:将文件test.txt的内容写入到标准输出(sys.stdout)
- python testscrip.py:执行Python脚本testscript。该脚本从其标准输入中读取,并将结果写入到标准输出。
- sort:读取标准输入sys.stdin中的所有文件,将各行按照字母顺序排序,并将结果写入到标准输出。
管道(|)将一个命令的标准输出链接到下一个命令的标准输入。
我们除了可以按顺序从头到尾读取,实际上,可在文件中移动进行随机存取。为此,可使用文件对象的两个方法:seek和tell。方法seek(offset[,whence])将当前位置(执行读取或写入的位置)移到offset和whence指定的地方。参数offset指定了字节(字符)数,而参数whence默认为io.SEEK_SET(o),这意味着偏移量是相对于文件开头的(偏移量不能为负数)。参数whence还可设置为io.SEEK_SET(1)或io.SEEK_END(2),其中前者表示相对于当前位置进行移动,而后者表示相对于文件末尾进行移动。实例代码如下:
f = open(r'D:\text\test.txt', 'w')
suc = f.write('01234567890123456789')
print(suc)
f.seek(5)
f.write('Hello World')
f.close()
f = open(r'D:\text\test.txt')
print(f.read())
# 方法tell()返回当前位于文件的什么位置
f = open(r'D:\text\test.txt')
print(f.read(3))
print(f.tell())
print(f.read(2))
print(f.tell())
执行的结果如下:
20
01234Hello World6789
012
3
34
5
2.3 读取和写入行
前面中介绍的都是逐个读取流中的字符,在现实中这么做并不实用。我们更多的是成行的读取,可使用方法readline。调用该方法时,可不提供任何的参数(默认读取一行并返回);也可提供一个非负整数,指定readline最多可读取多少个字符。要读取文件中的所有行,并以列表的方式返回它们,可使用方法readlines。
方法writelines与readlines相反:接收一个字符串列表,并将这些字符都写入到文件(或流)中。需要注意的是,写入时不会添加换行符,因此必须自行添加。另外没有方法writeline,因为可以使用write。
2.4 关闭文件
通常,程序退出时将自动关闭文件对象,因此是否将读取的文件关闭并不是很重要。但是,对于写入过的文件,一定要将其关闭,因为Python可能缓冲写入的数据。因此如果程序出现崩溃,数据可能根本不会写入到文件中。安全的做法是,使用完文件后就将其关闭。如果要重置缓冲,让所做的修改反映到映射文件中,但又不想关闭文件,可以使用方法flush。
要确保文件得以关闭,可使用一条try/finally语句,并在finally子句中调用close方法。
try:
finally:
file.close()
有一条专门为此设计的语句,with语句。
with open("test.txt") as f:
do_something(f)
with语句让你能够打开文件并将其赋值给一个变量。在语句体中,对文件进行操作,到达语句末尾时,将自动关闭文件,即便出现异常也是如此。
2.5 使用文件的基本方法
有如下的info.txt文件,内容如下:
Welcome to this file
There is nothing here
This is test info
f = open(r'D:\text\info.txt')
print(f.read(7))
print(f.read(4))
f.close()
f = open(r'D:\text\info.txt')
print(f.read())
f.close()
f = open(r'D:\text\info.txt')
for i in range(3):
print(str(i) + ':' + f.readline(), end='')
f.close()
print()
f = open(r'D:\text\info.txt')
print(f.readlines())
f.close()
输出结果如下:
Welcome
to
Welcome to this file
There is nothing here
This is test info
0:Welcome to this file
1:There is nothing here
2:This is test info
['Welcome to this file\n', 'There is nothing here \n', 'This is test info']
文件读写:
f = open(r'D:\text\language.txt')
lines = f.readlines()
print(lines)
f.close()
lines[1] = 'go\n'
f = open(r'D:\text\language.txt', 'w')
f.writelines(lines)
f.close()
输出结果如下:
['hello\n', 'java\n', 'python\n']
3.迭代文件内容
3.1 迭代字符、行
每次一个字符(或字节)
我们可以每次迭代一个字符,示例代码如下:
with open(r'D:\text\language.txt') as f:
while True:
char = f.read(1)
if not char: break
print(char)
每次一行
with open(r'D:\text\language.txt') as f:
while True:
line = f.readline()
if not line: break
print(line)
with open(r'D:\text\language.txt') as f:
for line in f:
print(line)
for line in open(r'D:\text\language.txt'):
print(line)