文件对象的方法
要读取文件内容,需要调用 f.read(size),这将读取一定数量的数据并返回字符串(文本模式下)或者字节对象(二进制模式下)。size 是一个可选的数值参数。当省略 size,或者此参数值为负数时,将读取文件的全部内容并将其返回。如果文件大小大于计算机内存,则应该在编程时处理这个问题,不能一次性全部读入文件内容。如果设置了此参数,最多读取和返回 size 字符(文本模式)或 size 字节(二进制模式)。如果已到达文件的结尾,f.read() 将返回一个空字符串('')。
例如,如果一个 demo.txt 文件内容为:
本文件只有这一行内容!
复制
with open('demo.txt', encoding='utf-8') as f:
content = f.read()
print(content)
print(repr(f.read()))
复制
运行结果:
本文件只有这一行内容!
''
复制
f.readline() 从文件中读取一行;换行符 (\n) 保留在字符串的末尾,如果文件不是以换行符结尾,则仅在文件的最后一行省略。这使得返回值明确无误;如果 f.readline() 返回空字符串,则表示已到达文件末尾,而空行由 '\n' 表示,该字符串仅包含一个换行符。
例如,如果一个 demo.txt 文件内容为:
本文件只有这2行内容,1!
本文件只有这2行内容,2!
复制
with open('demo.txt', encoding='utf-8') as f:
print(repr(f.readline()))
print(repr(f.readline()))
print(repr(f.readline()))
复制
运行结果:
'本文件只有这2行内容,1!\n'
'本文件只有这2行内容,2!'
''
复制
要从文件中读取行,可以在文件对象上循环。这是一种高效、快速的方法,并可使代码更简单:
with open('demo.txt', encoding='utf-8') as f:
for line in f:
print(repr(line))
复制
运行结果:
'本文件只有这2行内容,1!\n'
'本文件只有这2行内容,2!'
复制
如果想将文件的所有行读入到一个列表中,也可以使用 list(f) 或者 f.readlines()。
with open('demo.txt', encoding='utf-8') as f:
#mylist1 = list(f)
#print(repr(mylist1))
mylist2 = f.readlines()
print(repr(mylist2))
复制
运行结果:
['本文件只有这2行内容,1!\n', '本文件只有这2行内容,2!']
复制
f.write(string) 将 string 的内容写入文件,返回写入的字符数。
with open('1.txt', 'w') as f:
result = f.write('月落乌啼霜满天\n')
print(result)
复制
在写入其他类型的对象之前,需要将其转换为字符串(文本模式)或字节对象(二进制模式):
with open('1.txt', 'w') as f:
value = ('月落乌啼霜满天', '作者是谁?')
s = str(value) # 将元组转为字符串
f.write(s)
复制
文件内容:
('月落乌啼霜满天', '作者是谁?')
复制
f.tell() 返回一个整数,表示文件对象在文件中的当前位置,二进制模式下以字节数表示,文本模式下为一个不透明的数量。
with open('1.txt', 'w', encoding = 'utf-8') as f:
f.write('Moonset, rooks caw, frost fills the sky,\n')
f.write('maples and fishing lights, and sorrow before my bed.\n')
with open('1.txt', 'rt', encoding = 'utf-8') as f2:
f2.readline()
print('文本模式下,当前位置:', f2.tell())
with open('2.txt', 'w', encoding = 'utf-8') as f:
f.write('月落乌啼霜满天\n')
f.write('江枫渔火对愁眠\n')
with open('2.txt', 'rt', encoding = 'utf-8') as f2:
f2.readline()
print('文本模式下,当前位置:', f2.tell())
复制
要更改文件对象的位置,请使用 f.seek(offset, whence)。通过向参考点添加 offset 来计算位置;参考点由 whence 参数选择。其中值 0 表示从文件的开头开始计算,1 表示使用当前文件位置,2 表示使用文件的结尾作为参考点。whence 可以省略,默认为 0,使用文件的开头作为参考点。
with open('2.txt', 'wb+') as f:
print(f.write(b'0123456789abcdef'))
print(f.seek(5)) # 到文件的第6个字节
print(f.read(1))
print(f.seek(-3, 2)) # 从文件末尾开始第3个字节
print(f.read(1))
复制
运行结果
16
5
b'5'
13
b'd'
复制
在文本文件(在模式字符串中没有使用 b 打开的文件)中,只允许相对于文件开头的搜索(例外情况是使用 seek(0, 2) 搜索文件结尾),唯一有效的 offset 值是从 f.tell() 返回的值,或零。任何其他 offset 都会产生未定义的行为。
文件对象有一些额外的方法,例如 isatty() 和 truncate(),它们不太常用。
使用 json 保存结构化数据
可以很容易地从文件写入和读取字符串。数字稍微要麻烦些,因为 read() 方法只返回字符串,必须将字符串传递给 int() 之类的函数,int() 接受 '123' 之类的字符串并返回其数值 123。当想要保存更复杂的数据类型(如嵌套列表和字典)时,手动解析和序列化会变得复杂。
Python 允许使用流行的数据交换格式 JSON(JavaScript Object Notation),而不是让用户不断编写和调试代码以将复杂的数据类型保存到文件中。标准模块 json 可以接收 Python 数据层次结构,并将其转换为字符串表示形式;这个过程称为序列化。从字符串表示重构数据称为反序列化。在序列化和反序列化之间,表示对象的字符串可能存储在文件或数据中,或者通过网络连接发送到某台远程计算机。
注意:JSON 格式通常被现代应用程序用于数据交换。许多程序员已经熟悉它,这使得它成为互操作性的一个很好的选择。
如果有一个对象 x,可以用一行简单的代码查看其 JSON 字符串表示形式:
import json
x = [1, '第一名', '吕布']
print(json.dumps(x, ensure_ascii=False))
复制
运行结果:
[1, "第一名", "吕布"]
复制
dumps() 函数的另一个变体称为 dump(),它只是将对象序列化为文本文件。因此,如果 f 是一个打开以供写入的文本文件对象,我们可以这样做:
import json
with open("2.txt", "w", encoding = "utf-8") as f:
x = {}
x[1] = "吕布"
x[2] = "赵云"
json.dump(x, f, ensure_ascii=False)
复制
运行结果保存在 2.txt 文件中:
{"1": "吕布", "2": "赵云"}
复制
要再次解码对象,如果 f 是已打开用于读取的文本文件对象:
import json
with open("2.txt", "r", encoding = "utf-8") as f:
x = json.load(f)
print(x)
复制
运行结果:
{'1': '吕布', '2': '赵云'}
复制
这种简单的序列化技术可以处理列表和字典,但在 JSON 中序列化任意类实例需要一些额外的工作。json 模块的参考包含对此的解释。
官方文档:
https://docs.python.org/3.9/tutorial/inputoutput.html