Python io.BytesIO 的 write()、read() 和 getvalue() 方法如何工作?
How the write(), read() and getvalue() methods of Python io.BytesIO work?
我正在尝试理解 write() 和 read() 方法 io.BytesIO。 我的理解是我可以像使用文件一样使用 io.BytesIO 对象。
import io
in_memory = io.BytesIO(b'hello')
print( in_memory.read() )
上面的代码会 return b'hello' 正如预期的那样,但是下面的代码会 return 一个空字符串 b ''.
import io
in_memory = io.BytesIO(b'hello')
in_memory.write(b' world')
print( in_memory.read() )
我的问题是:
-io.BytesIO.write(b' world')
到底在做什么?
-io.BytesIO.read()和io.BytesIO.getvalue()有什么区别?
我认为答案与 io.BytesIO 是流对象有关,但我不清楚大局。
这是一个内存流,但仍然是一个流。该位置已存储,因此与任何其他流一样,如果您在写入后尝试读取,则必须重新定位:
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() )
打印:
b'hello world'
而 in_memory.getvalue()
不需要最后的 seek(0)
因为它 returns 从位置 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'
请注意,就像 write
('w'
) 模式下的文件流一样,初始字节 b'hello'
已被您编写的 b' world'
覆盖。
.getvalue()
只是 returns 流的全部内容,无论当前位置如何。
BytesIO
确实像一个文件,只是一个您可以读写的文件。令人困惑的部分可能是阅读和写作的位置是同一个。所以首先你要做:
in_memory = io.BytesIO(b'hello')
这会在 in_memory
中为您提供一个字节缓冲区,其中包含内容 b'hello'
并且 read/write 位置位于开头(在第一个 b'h'
之前)。当你这样做时:
in_memory.write(b' world')
您实际上是用 b' world'
覆盖了 b'hello'
(实际上又多了一个字节),现在您的位置在末尾(在最后一个 b'd'
之后)。所以当你这样做时:
print( in_memory.read() )
您什么也看不到,因为在 当前位置后 没有任何内容可读。但是,您可以使用 seek
移动位置,因此如果您这样做
import io
in_memory = io.BytesIO(b'hello')
in_memory.write(b' world')
in_memory.seek(0)
print( in_memory.read() )
你得到:
b' world'
请注意,您看不到开头的 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() )
输出:
b'hello world'
编辑:关于 getvalue
,正如其他答案所指出的,它为您提供了完整的内部缓冲区,与当前位置无关。这个操作显然不能用于文件。