【问题标题】:How the write(), read() and getvalue() methods of Python io.BytesIO work?Python io.BytesIO 的 write()、read() 和 getvalue() 方法如何工作?
【发布时间】:2018-11-26 16:53:56
【问题描述】:

我正在尝试了解 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 是一个流对象有关,但我并不清楚大局。

【问题讨论】:

    标签: python bytesio


    【解决方案1】:

    问题是您位于流的末尾。把这个位置想象成一个光标。一旦你写了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】:

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

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

      【讨论】:

        【解决方案3】:

        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,正如其他答案所指出的那样,它为您提供了完整的内部缓冲区,与当前位置无关。此操作显然不适用于文件。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-12-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-04-03
          相关资源
          最近更新 更多