从StringIO读取直到遇到某个字节的快速方法

2024-10-01 11:40:53 发布

您现在位置:Python中文网/ 问答频道 /正文

假设我有一些StringIO(来自cStringIO)。我想从中读取缓冲区,直到遇到某个字符/字节,比如“Z”,所以:

stringio = StringIO('ABCZ123')
buf = read_until(stringio, 'Z')  # buf is now 'ABCZ'
# strinio.tell() is now 4, pointing after 'Z'

在Python中实现这一点的最快方法是什么?谢谢你


Tags: read字节is字符now缓冲区untilbuf
3条回答
#!/usr/bin/env python3
import io


def iterate_stream(stream, delimiter, max_read_size=1024):
    """ Reads `delimiter` separated strings or bytes from `stream`. """
    empty = '' if isinstance(delimiter, str) else b''
    chunks = []
    while 1:
        d = stream.read(max_read_size)
        if not d:
            break
        while d:
            i = d.find(delimiter)
            if i < 0:
                chunks.append(d)
                break
            chunks.append(d[:i+1])
            d = d[i+1:]
            yield empty.join(chunks)
            chunks = []
    s = empty.join(chunks)
    if s:
        yield s


if __name__ == '__main__':
    print(next(iterate_stream(io.StringIO('ABCZ123'), 'Z')))
    print(next(iterate_stream(io.BytesIO(b'ABCZ123'), b'Z')))

我很失望这个问题只有一个关于堆栈溢出的答案,因为这是一个有趣和相关的问题。不管怎么说,因为只有奥夫戈洛文给出了解决方案,我觉得可能比较慢,所以我想了一个更快的解决方案:

def foo(stringio):
    datalist = []
    while True:
        chunk = stringio.read(256)
        i = chunk.find('Z')
        if i == -1:
            datalist.append(chunk)
        else:
            datalist.append(chunk[:i+1])
            break
        if len(chunk) < 256:
            break
    return ''.join(datalist)

这是分块读取io(可能在第一个块中找不到end char)。它非常快,因为没有为每个字符调用Python函数,相反,最大限度地使用C编写的Python函数。在

这比ovgolovin的解决方案快60倍左右。我运行timeit来检查它。在

i = iter(lambda: stringio.read(1),'Z')
buf = ''.join(i) + 'Z'

这里iter在这种模式下使用:iter(callable, sentinel) -> iterator。在

''.join(...)相当有效。最后一个添加'Z'''.join(i) + 'Z'的操作不是很好。但可以通过向迭代器添加'Z'来解决:

^{pr2}$

另一种方法是使用生成器:

def take_until_included(stringio):
    while True:
        s = stringio.read(1)
        yield s
        if s=='Z':
            return

i = take_until_included(stringio)
buf = ''.join(i)

我做了一些效率测试。所述技术的性能几乎相同:

http://ideone.com/dQGe5

相关问题 更多 >