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

时间:2015-10-28 15:22:21

标签: python inputstream

我正在寻找一种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

2 个答案:

答案 0 :(得分: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()

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

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 :(得分: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