将字节流解码为文本流很容易:
import io
f = io.TextIOWrapper(io.BytesIO(b'Test\nTest\n'), 'utf-8')
f.readline()在本例中,io.BytesIO(b'Test\nTest\n')是字节流,f是文本流。
我想做的正好相反。给定一个文本流或类文件对象,我希望在不处理整个流的情况下将其编码为字节流或类文件对象。
这就是我到目前为止所尝试的:
import io, codecs
f = codecs.getreader('utf-8')(io.StringIO('Test\nTest\n'))
f.readline()
# TypeError: can't concat str to bytes
f = codecs.EncodedFile(io.StringIO('Test\nTest\n'), 'utf-8')
f.readline()
# TypeError: can't concat str to bytes
f = codecs.StreamRecoder(io.StringIO('Test\nTest\n'), None, None,
codecs.getreader('utf-8'), codecs.getwriter('utf-8'))
# TypeError: can't concat str to bytes
f = codecs.encode(io.StringIO('Test\nTest\n'), 'utf-8')
# TypeError: utf_8_encode() argument 1 must be str, not _io.StringIO
f = io.TextIOWrapper(io.StringIO('Test\nTest\n'), 'utf-8')
f.readline()
# TypeError: underlying read() should have returned a bytes-like object, not 'str'
f = codecs.iterencode(io.StringIO('Test\nTest\n'), 'utf-8')
next(f)
# This works, but it's an iterator instead of a file-like object or stream.
f = io.BytesIO(io.StringIO('Test\nTest\n').getvalue().encode('utf-8'))
f.readline()
# This works, but I'm reading the whole stream before converting it.我使用的是Python 3.7
发布于 2018-07-30 07:06:27
您可以很容易地自己编写此代码;您只需决定如何进行缓冲即可。
例如:
class BytesIOWrapper(io.RawIOBase):
def __init__(self, file, encoding='utf-8', errors='strict'):
self.file, self.encoding, self.errors = file, encoding, errors
self.buf = b''
def readinto(self, buf):
if not self.buf:
self.buf = self.file.read(4096).encode(self.encoding, self.errors)
if not self.buf:
return 0
length = min(len(buf), len(self.buf))
buf[:length] = self.buf[:length]
self.buf = self.buf[length:]
return length
def readable():
return True我想这正是你想要的。
>>> f = BytesIOWrapper(io.StringIO("Test\nTest\n"))
>>> f.readline()
b'Test\n'
>>> f.readline()
b'Test\n'
>>> f.readline()
b''如果你想变得更聪明,你可能想要包装一个codecs.iterencode,而不是一次缓冲4K。或者,因为我们使用的是buffer,所以您可能希望创建一个BufferedIOBase而不是RawIOBase。此外,名为BytesIOWrapper的类可能应该处理write,但这是最简单的部分。最困难的部分是实现seek/tell,因为您不能在TextIOBase中任意查找;使查找开始和结束相当容易;另一方面,查找以前已知的位置很难(除非您依赖于TextIOBase.tell返回字节位置-这不是保证可以做到的,虽然TextIOWrapper可以,但StringIO不能…)。
无论如何,我认为这是如何编写最复杂的io类的最简单的演示。
https://stackoverflow.com/questions/51585110
复制相似问题