Python StreamIO从同一个流中读取和写入

问题描述 投票:3回答:2

我正在寻找一种pythonic方法来读取和写入流(在IOBase层次结构中),而不必通过seek()和tell()来管理流位置。这类似于套接字流将如何工作,其中接收端能够在接收的字节的同时连续读取。

我已经尝试将BufferedReader和BufferedWriter都连接到同一个原始流,但是一个上的操作会影响另一个上的流位置。 seek()/ tell()似乎直接传递给底层原始流。是否有其他IOBase类型可用于有效地作为IO流,其中支持并发输入和输出而无需管理流位置(类似于C ++ stringstream >>和<<)。

谢谢!

>>> import io
>>> buf = io.BytesIO()
>>> r = io.BufferedReader(buf)
>>> w = io.BufferedWriter(buf)
>>> w.write('foo bar')
7L
>>> r.read(1)
''
>>> r.tell()
0L
>>> w.flush()
>>> r.tell()
7L
>>> r.flush()
>>> r.tell()
7L
>>> w.tell()
7L
>>> buf.tell()
7L
python inputstream
2个回答
2
投票

你不能直接。

套接字与一对文件描述符是同源的,一个用于读取,一个用于写入。这就是为什么允许您在不使用不同操作之间的搜索的情况下读取和写入套接字的原因。

如果你真的想用StringIOBytesIO模拟一个套接字,那么只需构建一个包含一对或它们的自定义类。

它可能是这样的:

class BytesSocket(io.IOBase):
    def __init__(self, inputText):
        self.input = io.BytesIO(inputText)
        self.output = io.BytesIO()
    def read(self, n=-1):
        return self.input.read(n)
    def readinto(self, b):
        return self.input.readinto(b)
    def write(self, b):
        return self.output.write(b)
    def getoutvalue(self):
        return self.output.getvalue()

如果你需要一个loopback伪套接字(读取以前写过的内容),你可以使用:

class BytesLoop(io.IOBase):
    def __init__(self, inputText=''):
        self.buf = inputText
    def read(self, n=-1):
        inp = io.BytesIO(self.buf)
        b = inp.read(n)
        self.buf = self.buf[len(b):]
        return b
    def readinto(self, b):
        inp = io.BytesIO(buf)
        l = inp.readinto(b)
        self.buf = self.buf[l:]
        return l
    def write(self, b):
        outp = io.BytesIO()
        l = outp.write(b)
        self.buf += outp.getvalue()
        return l
    def getvalue(self):
        return self.buf

由于str(或unicode)是一个非可变序列,因此需要为每个io操作重新编写。您可以轻松使用可变的字符列表。您可以使用l = [c for c in s ]将字符串转换为列表,而使用s = ''.join(l)可以完成相反的操作。


1
投票

以下简单的字符串示例比Serge上面的第二个示例(至少如果流中保存的数据相对较小)运行的速度要快得多,并且适用于对同一流的简单读取和写入:

class BytesLoop:
    def __init__(self, s=b''):
        self.buffer = s

    def read(self, n=-1):
        chunk = self.buffer[:n]
        self.buffer = self.buffer[n:]
        return chunk

    def write(self, s):
        self.buffer += s
© www.soinside.com 2019 - 2024. All rights reserved.