我正在尝试理解io.BytesIO的write()和read()方法.我的理解是我可以使用io.BytesIO,因为我会使用File对象.
import io
in_memory = io.BytesIO(b'hello')
print( in_memory.read() )
Run Code Online (Sandbox Code Playgroud)
上面的代码将按预期返回b'hello',但下面的代码将返回一个空字符串b''.
import io
in_memory = io.BytesIO(b'hello')
in_memory.write(b' world')
print( in_memory.read() )
Run Code Online (Sandbox Code Playgroud)
我的问题是:
- io.BytesIO.write(b' world')到底做了什么?
- io.BytesIO.read()和io.BytesIO.getvalue()有什么区别?
我假设答案与io.BytesIO是一个流对象有关,但我不清楚大局.
BytesIO其行为确实像一个文件,只是一个既可以读又可以写的文件。也许令人困惑的部分是读取和写入位置是相同的。所以首先你要做:
in_memory = io.BytesIO(b'hello')
Run Code Online (Sandbox Code Playgroud)
这为您提供了一个字节缓冲区,其中in_memory包含内容b'hello'和开头的读/写位置(第一个之前b'h')。当你这样做时:
in_memory.write(b' world')
Run Code Online (Sandbox Code Playgroud)
您实际上正在覆盖b'hello'(b' world'并且实际上进一步获得了一个字节),现在您的位置位于末尾(在最后一个之后b'd')。所以当你这样做时:
print( in_memory.read() )
Run Code Online (Sandbox Code Playgroud)
您什么也看不到,因为当前位置之后没有任何内容可阅读。但是,您可以使用seek移动位置,因此如果您这样做
import io
in_memory = io.BytesIO(b'hello')
in_memory.write(b' world')
in_memory.seek(0)
print( in_memory.read() )
Run Code Online (Sandbox Code Playgroud)
你得到:
in_memory = io.BytesIO(b'hello')
Run Code Online (Sandbox Code Playgroud)
请注意,您看不到首字母,b'hello'因为它已被覆盖。如果想写在最初的内容之后,可以先求到最后:
import io
in_memory = io.BytesIO(b'hello')
in_memory.seek(0, 2)
in_memory.write(b' world')
in_memory.seek(0)
print( in_memory.read() )
Run Code Online (Sandbox Code Playgroud)
输出:
in_memory.write(b' world')
Run Code Online (Sandbox Code Playgroud)
编辑:关于getvalue,正如其他答案所指出的,它为您提供完整的内部缓冲区,与当前位置无关。这个操作显然不适用于文件。
这是一个内存流,但仍然是一个流。该位置已存储,因此,与其他任何流一样,如果您在编写后尝试阅读,则必须重新定位:
import io
in_memory = io.BytesIO(b'hello')
in_memory.seek(0,2) # seek to end, else we overwrite
in_memory.write(b' world')
in_memory.seek(0) # seek to start
print( in_memory.read() )
Run Code Online (Sandbox Code Playgroud)
印刷品:
b'hello world'
Run Code Online (Sandbox Code Playgroud)
while in_memory.getvalue()不需要最终值,seek(0)因为它从位置0返回流的内容。
问题是您位于流的末尾。将该位置想像为光标。编写完后b' world',光标将在流的末尾。尝试时.read(),您正在读取游标位置之后的所有内容-没什么,因此您得到了空的字节串。
要浏览流,可以使用.seek方法:
>>> import io
>>> in_memory = io.BytesIO(b'hello', )
>>> in_memory.write(b' world')
>>> in_memory.seek(0) # go to the start of the stream
>>> print(in_memory.read())
b' world'
Run Code Online (Sandbox Code Playgroud)
请注意,就像write('w')模式下的文件流一样,初始字节b'hello'已被写入覆盖b' world'。
.getvalue() 无论当前位置如何,都只返回流的全部内容。