io.BufferedReader的peek函数返回缓冲区中的所有文本
我在Windows 8上使用Python 3.4.1。
我想读取一个文件,使用一种可以提前查看一定数量字节的缓冲接口,同时也能读取字节。看起来io.BufferedReader
是个不错的选择。
可惜的是,io.BufferedReader.peek
似乎没什么用,因为它好像只是返回缓冲区里所有的字节,而不是我请求的数量。实际上,这在这个函数的文档中是允许的(我强调的部分):
peek([size]) 从流中返回字节,而不移动位置。最多只会对原始流进行一次读取来满足这个调用。返回的字节数可能会少于或多于请求的数量。
为了展示我认为的无用行为,我有一个名为Test1.txt
的测试文件:
first line
second line
third line
我在IDLE中这样创建io.BufferedReader
对象:
>>> stream = io.BufferedReader(io.FileIO('Test1.txt'))
然后我请求两个字节,
>>> stream.peek(2)
b'first line\r\nsecond line\r\nthird line'
咦?这就是我系统默认缓冲区大小里的所有文本(在我的系统上是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'
为了明确,以下是我期望看到的输出:
>>> stream = io.BufferedReader(io.FileIO('Test1.txt'))
>>> stream.peek(2)
b'fi'
>>> stream.read(1)
b'f'
>>> stream.peek(2)
b'ir'
也就是说,一个典型的缓冲流。
我在构造这个BufferedReader
时做错了什么?我该如何在Python 3.4.1中观察到我期望的行为呢?
1 个回答
5
.peek()
的确是用来返回当前的缓冲区内容。如果你把它和 .read()
一起使用,你会发现每次读取后,缓冲区返回的数据会越来越少,直到缓冲区再次被填满。
对于 .peek()
的大多数用途来说,这样的设计是完全可以接受的。当缓冲区为空时,返回的字节数可以帮助你限制从底层输入输出源预期获取的数据量,这一点在该源在读取时可能会阻塞的情况下尤其重要。
你只需要对返回的值进行切片处理:
stream.peek(num)[:num]