Python io.BytesIO的write(),read()和getvalue()方法如何工作?

时间:2018-11-26 16:53:56

标签: python bytesio

我试图了解 io.BytesIO write() read()方法。 我的理解是,我可以像使用文件一样使用 io.BytesIO 对象。

import io
in_memory = io.BytesIO(b'hello')
print( in_memory.read() )

上面的代码将按预期返回 b'hello',但是下面的代码将返回空字符串 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 有关,但是我不清楚。

3 个答案:

答案 0 :(得分:4)

这是一个内存流,但仍然是一个流。位置已存储,因此,与其他任何流一样,如果您尝试在写入后阅读,则必须重新定位:

let arr = [{Code: "AT", Country: "Austria", Nationality: "Austrian"}
 ,{Code: "BE", Country: "Belgium", Nationality: "Belgian"}
 ,{Code: "CH", Country: "Switzerland", Nationality: "Swiss"}
 ,{Code: "DE", Country: "Germany", Nationality: "German"}
 ,{Code: "ES", Country: "Spain", Nationality: "Spanish"}
 ,{Code: "IT", Country: "Italy", Nationality: "Italian"}
 ,{Code: "NL", Country: "Netherlands", Nationality: "Dutch"}
 ,{Code: "PL", Country: "Poland", Nationality: "Polish"}]

arr.sort((a,b) => a.Country.localeCompare(b.Country))

console.log(arr)

打印:

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(),因为它从位置0返回流的内容。

答案 1 :(得分:4)

问题在于您位于流的末尾。将该位置想像为光标。写入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()仅返回流的全部内容,而与当前位置无关。

答案 2 :(得分:2)

BytesIO的行为就像一个文件,只有一个文件可以读取和写入。可能令人困惑的部分是读写位置是相同的。所以首先你要做:

in_memory = io.BytesIO(b'hello')

这将为您提供in_memory中的字节缓冲区,其内容为b'hello',并且读/写位置位于开头(在第一个b'h'之前)。当您这样做时:

in_memory.write(b' world')

您实际上用b'hello'覆盖了b' world'(实际上又增加了一个字节),现在位置在末尾(在最后一个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,如其他答案所指出,它为您提供了完整的内部缓冲区,而与当前位置无关。该操作显然不适用于文件。