文件对象概述
文件对象是指对外提供面向文件 API 以使用下层资源的对象(带有 read() 或 write() 这样的方法),也被称作流或文件类对象。
有三种类别的文件对象: 原始二进制文件, 缓冲二进制文件 以及
文本文件。三种类别下还有子类别,因创建方式的不同得到不同类别文件对象。它们的接口定义均在 io 模块中。创建文件对象的规范方式是使用 open() 函数。
用户代码直接操作原始流的用法非常罕见。不过,可以通过在禁用缓冲的情况下以二进制模式打开文件来创建原始流:
f = open("test.txt","rb", buffering=0)
f
<_io.FileIO name='test.txt' mode='rb' closefd=True>
缓冲二进制流不执行编码、解码或换行转换。这种类型的流可以用于所有类型的非文本数据(例如图片,视频),并且还可以在需要手动控制文本数据的处理时使用。创建缓冲二进制流的最简单方法是使用 open(),并在模式中指定 ‘b’:
f = open("test.txt","rb")
f
<_io.BufferedReader name='test.txt'>
文本流生成 str 对象。这意味着,无论何时后台存储是由字节组成的,数据的编码和解码都是透明的,并且可以选择转换特定于平台的换行符。创建文本流的最简单方法是使用 open(),可以选择指定编码:
f = open("test.txt",encoding="utf-8")
f
<_io.TextIOWrapper name='test.txt' mode='r' encoding='utf-8'>
所有流对提供给它们的数据类型都很敏感。例如将 str 对象给二进制流的 write() 方法会引发 TypeError。
f = open("test.txt","ab")
f.write('写入内容')
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-19-a9efd264aca2> in <module>
1 f = open("test.txt","ab")
----> 2 f.write('写入内容')
TypeError: a bytes-like object is required, not 'str'
内存中的流也可以作为文件对象使用:
import io
f = io.StringIO("some initial text data")
print(f)
f.read()
<_io.StringIO object at 0x000001BE348D2040>
'some initial text data'
f = io.BytesIO(b"some initial binary data: \x00\x01")
print(f)
f.read()
<_io.BytesIO object at 0x000001BE348D3310>
b'some initial binary data: \x00\x01'
open() 函数打开文件,创建流后,会使文件在一段不确定的时间内处于打开状态。这在简单脚本中不是问题,但对于较大的应用程序来说可能是个问题。此时用 close() 方法刷新并关闭流(或直接使用 with 语句打开)是明智的做法。
f = open("test.txt",encoding="utf-8")
print(f.read())
f.close()
为什么要掌握自学能力?
未来还很长。
读取文件内容
打开方式不同,会创建不同类型的文件对象(流),不同类型的文件对象,可能有不同的属性或方法。
下列检查或读取内容的属性或方法,是多数文件对象通用的:
- readable() 如果可以读取流,则返回 True 。否则为 False ,且 read() 将引发 OSError 错误。
f = open('test.txt')
f.readable()
True
f = open('test.txt',encoding='utf-8')
f.read()
'为什么一定要掌握自学能力?\n未来的日子还很长,\n这世界进步得太快,\n没有自学能力,\n没有未来。'
f = open('test.txt',encoding='utf-8')
f.read(12)
'为什么一定要掌握自学能力'
36
f.read() # 再次读取,将读取剩下未读部分
'?\n未来的日子还很长,\n这世界进步得太快,\n没有自学能力,\n没有未来。'
''
- seek(offset, whence=0) 将流位置修改到给定的字节 offset。返回新的绝对位置。
0
'为什么一定要掌握自学能力?\n未来的日子还很长,\n这世界进步得太快,\n没有自学能力,\n没有未来。'
- readline(size=-1) 从流中读取并返回一行。如果指定了 size,将至多读取 size 个字节。
f = open('test.txt',encoding='utf-8')
f.readline()
'为什么一定要掌握自学能力?\n'
f.readline(2) # 再次读取,将读取剩下未读部分
'未来'
- readlines(hint=-1) 从流中读取并返回包含多行的列表。可以指定 hint 来控制要读取的行数。指定行数可以多于实际。
f = open('test.txt',encoding='utf-8')
f.readlines(1)
['为什么一定要掌握自学能力?\n']
f.readlines(10) # 再次读取,将读取剩下未读部分
['未来的日子还很长,\n', '这世界进步得太快,\n']
- 使用
for line in file: ...
就足够对文件对象进行迭代了,可以不必调用 file.readlines()。
f = open('test.txt',encoding='utf-8')
for line in f:
print(line)
为什么一定要掌握自学能力?
未来的日子还很长,
这世界进步得太快,
没有自学能力,
没有未来。
False
- close() 刷新并关闭此流。无论读写操作,最后都应该关闭流。如果文件已经关闭,则此方法无效。文件关闭后,对文件的任何操作(例如读取或写入)都会引发 ValueError 。为方便起见,允许多次调用此方法。但是,只有第一个调用才会生效。
f.close()
f.close()
f.closed
True
文件写入内容
打开方式不同,会创建不同类型的文件对象(流),不同类型的文件对象,可能有不同的属性或方法。
打开模式不同,写入内容的方式也会不同,详见 open() 打开文件。
下列检查或写入内容的属性或方法,是多数文件对象通用的:
- writable() 如果流支持写入则返回 True。如为 False,则 write() 将引发 OSError。
f = open('test.txt','a',encoding='utf-8')
f.writable()
True
f = open('test.txt')
f.writable()
f.write('这世界进步得太快,')
---------------------------------------------------------------------------
UnsupportedOperation Traceback (most recent call last)
<ipython-input-1-7bf449cf8958> in <module>
1 f = open('test.txt')
2 f.writable()
----> 3 f.write('这世界进步得太快,')
UnsupportedOperation: not writable
- write() 将字符串或字节串写入到流并返回写入的字符或字节数。对于阻塞流(需要刷新才能将内容写入文件),写入内容在缓冲区(打开文件看不到写入的内容)。
f = open('test.txt','a+',encoding='utf-8')
f.write('\n这世界进步得太快,')
10
- flush() 刷新流的写入缓冲区(打开文件将看到写入的内容)。这对只读和非阻塞流不起作用。
- writelines(lines) 将行列表写入到流。不会添加行分隔符,因此通常所提供的每一行都带有末尾行分隔符。对于阻塞流,写入内容在缓冲区。
f = open('test.txt','a+',encoding='utf-8')
f.writelines(['\n没有自学能力,\n', '没有未来。'])
137
''
0
'为什么一定要掌握自学能力?\n未来的日子还很长,\n这世界进步得太快,\n没有自学能力,\n没有未来。'
False
- close() 刷新并关闭此流。无论读写操作,最后都应该关闭流。如果文件已经关闭,则此方法无效。文件关闭后,对文件的任何操作(例如读取或写入)都会引发 ValueError 。为方便起见,允许多次调用此方法。但是,只有第一个调用才会生效。
f.close()
f.close()
f.closed
True