io.BufferedReader peek函数返回缓冲区中的所有文本

dun*_*cks 5 python

我在Windows 8上使用Python 3.4.1.

我想读一个带缓冲接口的文件,它允许我查看前面的一定数量的字节以及读取字节.io.BufferedReader似乎是正确的选择.

不幸的是,io.BufferReader.peek似乎没用,因为它似乎只返回缓冲区中存储的所有字节,而不是请求的数字.事实上,这个函数的文档允许这样做(强调我的):

peek([size])从流中返回字节而不提升位置.最多只对原始流进行一次读取以满足调用.返回的字节数可能少于或多于请求的数量.

为了演示我认为无用的行为,我有以下测试文件Test1.txt:

first line
second line
third line
Run Code Online (Sandbox Code Playgroud)

我io.BufferedReader在IDLE中创建这样的对象:

>>> stream = io.BufferedReader(io.FileIO('Test1.txt'))
Run Code Online (Sandbox Code Playgroud)

然后要求两个字节,

>>> stream.peek(2)
b'first line\r\nsecond line\r\nthird line'
Run Code Online (Sandbox Code Playgroud)

嗯?这只是默认缓冲区大小中的所有文本(在我的系统上是8192字节).如果我更改此默认值,我可以确认peek()只是返回缓冲区的内容,

>>> stream2 = io.BufferedReader(io.FileIO('Test1.txt'), buffer_size=2)
>>> stream2.peek(17)
b'fi'
>>> stream2.peek(17)
b'fi'
>>> stream2.read(2)
b'fi'
>>> stream2.peek(17)
b'rs'
Run Code Online (Sandbox Code Playgroud)

需要说明的是,以下是我希望看到的输出:

>>> stream = io.BufferedReader(io.FileIO('Test1.txt'))
>>> stream.peek(2)
b'fi'
>>> stream.read(1)
b'f'
>>> stream.peek(2)
b'ir'
Run Code Online (Sandbox Code Playgroud)

也就是说,典型的缓冲流.

我在构建这个时做错了BufferedReader什么?如何观察我期望在Python 3.4.1中看到的行为?

Mar*_*ers 5

.peek()确实实现为返回当前缓冲区;如果将其与.read()调用结合起来,您会发现返回的缓冲区越来越少,直到缓冲区再次填满。

对于大多数目的来说,.peek()这已经足够了。如果缓冲区为空,字节数可让您限制底层 I/O 源所需的数据量,如果该源在读取时发生阻塞,则这一点很重要。

简单地对返回值进行切片:

stream.peek(num)[:num]
Run Code Online (Sandbox Code Playgroud)

  • 这对我来说没有意义:为什么 `.peek()` 需要读取多个字节呢?如果函数所做的只是返回内部缓冲区中的任何内容,则要读取的字节数似乎没有用处。 (7认同)
  • @wrtmu:基本上,如果没有缓冲数据,则字节数将传递给内部读取调用,这就是限制发挥作用的地方。 (2认同)