Val*_*tin 64
为简单起见,我们现在考虑写作而不是阅读.
所以当你使用时open()说:
with open("test.dat", "wb") as f:
f.write(b"Hello World")
f.write(b"Hello World")
f.write(b"Hello World")
Run Code Online (Sandbox Code Playgroud)
执行后,test.dat将创建一个名为的文件,包含Hello World.在将数据写入文件后,数据不会保留在内存中(除非由名称保存).
现在当你考虑io.BytesIO():
with io.BytesIO() as f:
f.write(b"Hello World")
f.write(b"Hello World")
f.write(b"Hello World")
Run Code Online (Sandbox Code Playgroud)
它不是将内容写入文件,而是写入内存缓冲区.换句话说,一块RAM.基本上写下以下内容将是等效的:
buffer = b""
buffer += b"Hello World"
buffer += b"Hello World"
buffer += b"Hello World"
Run Code Online (Sandbox Code Playgroud)
关于带有with语句的示例,最后还会有一个del buffer.
这里的关键区别是优化和性能.io.BytesIO能够进行一些优化,使其比简单地b"Hello World"逐个连接所有更快.
只是为了证明它是一个小基准:
import io
import time
begin = time.time()
buffer = b""
for i in range(0, 50000):
buffer += b"Hello World"
end = time.time()
seconds = end - begin
print("Concat:", seconds)
begin = time.time()
buffer = io.BytesIO()
for i in range(0, 50000):
buffer.write(b"Hello World")
end = time.time()
seconds = end - begin
print("BytesIO:", seconds)
Run Code Online (Sandbox Code Playgroud)
除了性能增益之外,使用BytesIO而不是连接具有BytesIO可以用来代替文件对象的优点.所以说你有一个期望文件对象写入的函数.然后你可以给它内存缓冲区而不是文件.
不同之处在于open("myfile.jpg", "rb")只需加载并返回内容myfile.jpg; 然而,BytesIO再次只是一个包含一些数据的缓冲区.
因为BytesIO它只是一个缓冲区 - 如果你想稍后将内容写入文件 - 你必须这样做:
buffer = io.BytesIO()
# ...
with open("test.dat", "wb") as f:
f.write(buffer.getvalue())
Run Code Online (Sandbox Code Playgroud)
另外,你没有提到一个版本; 我正在使用Python 3.与示例相关:我使用的是with语句而不是调用f.close()
使用open打开硬盘上的文件.根据您使用的模式,您可以从磁盘读取或写入(或两者).
一个BytesIO对象不与磁盘上的任何真正的文件关联.它只是一块内存,就像文件一样.它与返回的文件对象具有相同的API open(使用模式r+b,允许读取和写入二进制数据).
BytesIO(StringIO当它需要将数据传递给期望获得文件对象的API时,或者您希望直接传递数据的位置时,它可能非常有用).您可以将输入数据加载BytesIO到库中之前加载.返回后,您可以BytesIO使用该getvalue()方法获取库写入文件的任何数据.(当然,你通常只需要做其中一个.)