我正在尝试理解io的write((和read((方法。BytesIO。我的理解是我可以使用io。BytesIO,因为我会使用文件对象
import io
in_memory = io.BytesIO(b'hello')
print( in_memory.read() )
上面的代码将按预期返回b'hello',但下面的代码将返回一个空字符串b'' 我的问题是: - -io之间有什么区别。BytesIO.read((和io。BytesIO.getvalue((? 我认为答案与io有关。BytesIO是一个流对象,但我不清楚大局。import io
in_memory = io.BytesIO(b'hello')
in_memory.write(b' world')
print( in_memory.read() )
io.BytesIO.write(b' world')
究竟在做什么?
问题是您处于流的末尾。把这个位置想象成一个光标。一旦您编写了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' world'
的写入已经覆盖了初始字节b'hello'
。
.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() )
打印:
b'hello world'
而CCD_ 10不需要最终的CCD_。
BytesIO
的行为确实像一个文件,只是一个既能读又能写的文件。令人困惑的部分可能是,阅读和写作的位置是相同的。所以你首先要做的是:
in_memory = io.BytesIO(b'hello')
这在in_memory
中为您提供了一个字节缓冲区,内容为b'hello'
,读/写位置在开头(在第一个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
,正如其他答案所指出的,它为您提供了完整的内部缓冲区,与当前位置无关。此操作显然不适用于文件。