web-dev-qa-db-ja.com

Python io.BytesIOのwrite()、read()およびgetvalue()メソッドはどのように動作しますか?

io.BytesIOwrite()およびread()メソッドを理解しようとしています。私の理解では、Fileオブジェクトを使用するのと同じように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がストリームオブジェクトに関連していると思いますが、全体像ははっきりしていません。

8
Robert

問題は、あなたがストリームの最後にいるということです。カーソルのような位置を考えてください。 _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()は、現在の位置に関係なく、ストリームのコンテンツ全体を返すだけです。

6
johnpaton

これはメモリストリームですが、それでもストリームです。位置は保存されるため、他のストリームと同様に、書き込み後に読み取りを試みる場合は、位置を変更する必要があります。

_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からストリームのコンテンツを返すため、最後のseek(0)を必要としません。

BytesIOはファイルのように動作しますが、読み取りと書き込みの両方が可能なファイルのみです。混乱する部分は、おそらく、読み取りと書き込みの位置が同じであることです。まず最初に:

in_memory = io.BytesIO(b'hello')

これにより、in_memoryに、b'hello'の内容と、先頭(最初のb'h'の前)に読み取り/書き込み位置を持つバイトバッファーができます。行うとき:

in_memory.write(b' world')

b'hello'b' world'を効果的に上書きし(実際にはさらに1バイトを取得)、最後に(最後の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'は表示されないことに注意してください。最初のコンテンツの後にafterを書きたい場合は、最初に最後までシークできます:

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 について、他の回答で指摘されているように、現在の位置に関係なく、完全な内部バッファーを提供します。この操作は明らかにファイルには使用できません。

2
jdehesa